4 * Copyright 2001,2004 Develer S.r.l. (http://www.develer.com/)
5 * Copyright 1999,2000,2001 Bernardo Innocenti <bernie@develer.com>
6 * This file is part of DevLib - See devlib/README for information.
9 * \brief Semaphore based synchronization services.
13 * \author Bernardo Innocenti <bernie@develer.com>
18 * Revision 1.2 2004/06/03 11:27:09 bernie
19 * Add dual-license information.
21 * Revision 1.1 2004/05/23 17:27:00 bernie
22 * Import kern/ subdirectory.
34 * \brief Initialize a Semaphore structure
36 void sem_init(struct Semaphore *s)
38 INITLIST(&s->wait_queue);
45 * \brief Attempt to lock a semaphore without waiting.
47 * \return true in case of success, false if the semaphore
48 * was already locked by someone else.
50 * \note each call to sem_attempt() must be matched by a
51 * call to sem_release().
53 bool sem_attempt(struct Semaphore *s)
56 if ((!s->owner) || (s->owner == CurrentProcess))
58 s->owner = CurrentProcess;
69 * \brief Lock a semaphore.
71 * If the semaphore is already owned by another process, the caller
72 * process will be enqueued into the waiting list and sleep until
73 * the semaphore is available.
75 * \note Each call to sem_obtain() must be matched by a
76 * call to sem_release().
78 * \note This routine is optimized for highest speed in
79 * the most common case: the semaphore is free or locked
80 * by the calling process itself. Rearranging this code
81 * is probably a bad idea.
83 void sem_obtain(struct Semaphore *s)
87 /* Is the semaphore already locked by another process? */
88 if (s->owner && (s->owner != CurrentProcess))
90 /* Append calling process to the wait queue */
91 ADDTAIL(&s->wait_queue, (Node *)CurrentProcess);
94 /* We will awake only when the current owner calls
95 * ReleaseSemaphore(). Then, the semaphore will already
102 /* The semaphore is free: lock it */
103 s->owner = CurrentProcess;
111 * \brief Releases a lock on a previously locked semaphore.
113 * If the nesting count of the semaphore reaches zero,
114 * the next process waiting for it will be awaken.
116 * \note This routine is optimized for highest speed in
117 * the most common case: the semaphore has been locked just
118 * once and nobody else was waiting for it. Rearranging
119 * this code is probably a bad idea.
121 void sem_release(struct Semaphore *s)
125 /* Decremement nesting count and check if the semaphore
126 * has been fully unlocked
128 if (--s->nest_count == 0)
130 /* Disown semaphore */
133 /* Anybody still waiting for this semaphore? */
134 if (!ISLISTEMPTY(&s->wait_queue))
136 /* Give semaphore to the first applicant */
137 Process *proc = (Process *)s->wait_queue.head;
138 REMOVE((Node *)proc);