| | 283 | Maintenant, vous n'allez pas avoir à écrire le code des barrières mais voue allez devoir répondre à quelques questions |
| | 284 | {{{#!c |
| | 285 | #define MAGIC_BARRIER 0xDEADBABA |
| | 286 | |
| | 287 | struct thread_barrier_s { |
| | 288 | int magic; ///< magic number to check the validity of the barrier |
| | 289 | spinlock_t lock; ///< protection against parallel modifications |
| | 290 | size_t expected; ///< number of expected threads |
| | 291 | size_t waiting; ///< number of threads waiting |
| | 292 | list_t wait; ///< list element to chain threads that are wainting for the mutex |
| | 293 | }; |
| | 294 | |
| | 295 | int thread_barrier_init (thread_barrier_t * barrier, size_t count) |
| | 296 | { |
| | 297 | thread_barrier_t b = *barrier; // get the barrier pointer |
| | 298 | |
| | 299 | if (count == 0) return EINVAL; // count must be > 0 |
| | 300 | |
| | 301 | if (b == NULL) { // if we need a new barrier |
| | 302 | b = kmalloc (sizeof (struct thread_barrier_s)); // allocates a new barrier |
| | 303 | if (b == NULL) return ENOMEM; // test if there is enough memory |
| | 304 | b->magic = MAGIC_BARRIER; // tell it is a BARRIER |
| | 305 | b->lock = 0; // free the lock |
| | 306 | b->expected = count; // init the expected threads |
| | 307 | b->waiting = 0; // init the counter of waiting threads |
| | 308 | list_init (&b->wait); // init the waiting list |
| | 309 | *barrier = b; // at last, init. the return variable |
| | 310 | return SUCCESS; // it's fine |
| | 311 | } |
| | 312 | |
| | 313 | if (b && (b->magic != MAGIC_BARRIER)) return EINVAL; // it is not an old barrier |
| | 314 | |
| | 315 | spin_lock (&b->lock); // get the ownership |
| | 316 | if (b->waiting != 0) { // if someone is waiting |
| | 317 | spin_lock (&b->lock); // release the ownership |
| | 318 | return EBUSY; // return an error |
| | 319 | } |
| | 320 | |
| | 321 | b->expected = count; // set the number of expected threads |
| | 322 | spin_lock (&b->lock); // release the ownership |
| | 323 | |
| | 324 | return SUCCESS; // it's fine |
| | 325 | } |
| | 326 | |
| | 327 | int thread_barrier_wait (thread_barrier_t * barrier) |
| | 328 | { |
| | 329 | thread_barrier_t b = *barrier; // get the barrier pointer |
| | 330 | |
| | 331 | if (b == NULL) return EINVAL; // b is not created |
| | 332 | if (b && (b->magic != MAGIC_BARRIER)) return EINVAL; // check that it is barrier (MAGIC) |
| | 333 | |
| | 334 | spin_lock (&b->lock); // get the ownership |
| | 335 | b->waiting++; // the current thread is the newcomer |
| | 336 | if (b->waiting == b->expected) { // |
| | 337 | list_foreach (&b->wait, waiting_item) { // |
| | 338 | list_unlink (waiting_item); // |
| | 339 | thread_t t = thread_item (waiting_item); // get the pointer of a waiting thread |
| | 340 | thread_notify (t); // |
| | 341 | } |
| | 342 | b->waiting = 0; // |
| | 343 | spin_unlock (&b->lock); // |
| | 344 | } else { |
| | 345 | thread_addlast (&b->wait, ThreadCurrent); // the current thread in the wait. list |
| | 346 | spin_unlock (&b->lock); // |
| | 347 | thread_wait (); // |
| | 348 | |
| | 349 | return SUCCESS; // it's fine |
| | 350 | } |