1/** \file 2 * \brief Example application using threads - a more complex 3 * example using synchronisation 4 */ 5 6/* 7 * Copyright (c) 2010, ETH Zurich. 8 * All rights reserved. 9 * 10 * This file is distributed under the terms in the attached LICENSE file. 11 * If you do not find this file, copies can be found by writing to: 12 * ETH Zurich D-INFK, Universitaetstrasse 6, CH-8092 Zurich. Attn: Systems Group. 13 */ 14 15#include <stdio.h> 16#include <string.h> 17 18#include <barrelfish/barrelfish.h> 19 20#include <barrelfish/threads.h> 21 22 23// data to pass to each thread 24struct my_thread_data { 25 int t_num; 26 struct thread *t_id; 27 struct thread_mutex *mutex; 28 int *start_cntr; 29 struct thread_sem *sem; 30 int ret; 31}; 32 33// the code that each thread runs 34static int my_thread(void *data) 35{ 36 struct my_thread_data *t_data = data; 37 int thread_num = t_data->t_num; 38 39 thread_mutex_lock(t_data->mutex); 40 (*(t_data->start_cntr))++; 41 thread_mutex_unlock(t_data->mutex); 42 43 printf("this is thread %d saying hello\n", thread_num); 44 45 thread_sem_post(t_data->sem); 46 47 return thread_num; 48} 49 50int main(int argc, char *argv[]) 51{ 52 errval_t err; 53 int num_threads = 0; 54 55 // # of threads to start 56 if (argc == 2) { 57 num_threads = atoi(argv[1]); 58 debug_printf("starting %d threads\n", num_threads); 59 } else { 60 printf("usage %s num_threads\n", argv[0]); 61 return EXIT_FAILURE; 62 } 63 64 65 // setup lock, counter, and semaphore 66 struct thread_mutex mutex = THREAD_MUTEX_INITIALIZER; 67 thread_mutex_init(&mutex); 68 int start_cntr = 0; 69 struct thread_sem sem = THREAD_SEM_INITIALIZER; 70 thread_sem_init(&sem, 0); 71 72 // set thread argument data 73 struct my_thread_data *t_data; 74 t_data = malloc(num_threads*sizeof(struct my_thread_data)); 75 assert(t_data != NULL); 76 77 78 // start threads 79 for (int i = 0; i < num_threads; i++) { 80 t_data[i].t_num = i; 81 t_data[i].mutex = &mutex; 82 t_data[i].start_cntr = &start_cntr; 83 t_data[i].sem = &sem; 84 85 t_data[i].t_id = thread_create(my_thread, &(t_data[i])); 86 if (t_data[i].t_id == NULL) { 87 debug_printf("ERROR: starting thread %d\n", i); 88 } 89 debug_printf("started thread %d\n", i); 90 } 91 92 // wait until all started 93 while (start_cntr != num_threads) { 94 thread_yield(); 95 } 96 97 debug_printf("all threads started\n"); 98 99 // wait until all finished 100 for (int i = 0; i < num_threads; i++) { 101 thread_sem_wait(&sem); 102 } 103 104 debug_printf("all threads finished\n"); 105 106 // cleanup: join all threads 107 for (int i = 0; i < num_threads; i++) { 108 err = thread_join(t_data[i].t_id, &(t_data[i].ret)); 109 if (err_is_ok(err)) { 110 debug_printf("joined thread %d, return value: %d\n", 111 i, t_data[i].ret); 112 } else { 113 DEBUG_ERR(err, "in thread_join for thread %d", i); 114 } 115 } 116 117 debug_printf("finished.\n"); 118 119 return EXIT_SUCCESS; 120} 121 122