1 /*
2  * Copyright (c) 2020 Intel Corporation
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #include <zephyr/kernel.h>
8 #include <zephyr/arch/cpu.h>
9 
10 #define NUM_THREADS 20
11 #define STACK_SIZE (1024)
12 
13 K_THREAD_STACK_ARRAY_DEFINE(tstacks, NUM_THREADS, STACK_SIZE);
14 
15 static struct k_thread t[NUM_THREADS];
16 
17 K_MUTEX_DEFINE(mutex);
18 K_CONDVAR_DEFINE(condvar);
19 
20 static int done;
21 
worker_thread(void * p1,void * p2,void * p3)22 void worker_thread(void *p1, void *p2, void *p3)
23 {
24 	const int myid = (long)p1;
25 	const int workloops = 5;
26 
27 	for (int i = 0; i < workloops; i++) {
28 		printk("[thread %d] working (%d/%d)\n", myid, i, workloops);
29 		k_sleep(K_MSEC(500));
30 	}
31 
32 	/*
33 	 * we're going to manipulate done and use the cond, so we need the mutex
34 	 */
35 	k_mutex_lock(&mutex, K_FOREVER);
36 
37 	/*
38 	 * increase the count of threads that have finished their work.
39 	 */
40 	done++;
41 	printk("[thread %d] done is now %d. Signalling cond.\n", myid, done);
42 
43 	k_condvar_signal(&condvar);
44 	k_mutex_unlock(&mutex);
45 }
46 
main(void)47 int main(void)
48 {
49 	k_tid_t tid[NUM_THREADS];
50 
51 	done = 0;
52 
53 	for (int i = 0; i < NUM_THREADS; i++) {
54 		tid[i] =
55 			k_thread_create(&t[i], tstacks[i], STACK_SIZE,
56 					worker_thread, INT_TO_POINTER(i), NULL,
57 					NULL, K_PRIO_PREEMPT(10), 0, K_NO_WAIT);
58 	}
59 	k_sleep(K_MSEC(1000));
60 
61 	k_mutex_lock(&mutex, K_FOREVER);
62 
63 	/*
64 	 * are the other threads still busy?
65 	 */
66 	while (done < NUM_THREADS) {
67 		printk("[thread %s] done is %d which is < %d so waiting on cond\n",
68 		       __func__, done, (int)NUM_THREADS);
69 
70 		/* block this thread until another thread signals cond. While
71 		 * blocked, the mutex is released, then re-acquired before this
72 		 * thread is woken up and the call returns.
73 		 */
74 		k_condvar_wait(&condvar, &mutex, K_FOREVER);
75 
76 		printk("[thread %s] wake - cond was signalled.\n", __func__);
77 
78 		/* we go around the loop with the lock held */
79 	}
80 
81 	printk("[thread %s] done == %d so everyone is done\n",
82 		__func__, (int)NUM_THREADS);
83 
84 	k_mutex_unlock(&mutex);
85 	return 0;
86 }
87