1 os_semaphore* CreateSemaphore(UCHAR semVal)
2 {
3 os_semaphore* temp_semaphore;
4
5 temp_semaphore = (os_thread*)g_freesemaphores;
6
7 if (temp_semaphore == NULL) return -1;
8
9 // pop a free thread from the list
10 g_freesemaphores = temp_semaphore->next;
11 g_freesemaphores->prev = NULL;
12
13 // push the free thread on the used threads list
14 temp_semaphore->next = g_usedsemaphores;
15 g_usedsemaphores->prev = temp_semaphore;
16 g_usedsemaphores = temp_semaphore;
17
18 temp_semaphore->remaining = semVal;
19
20 return temp_semaphore;
21 }
22 /*
23 void FreeSemaphore(os_semaphore* semaphore)
24 {
25 // this is harder than threadsem since its not always equal g_usedsemaphores
26 }
27 */
28 os_threadsem* CreateThreadSem(os_thread *thread)
29 {
30 os_threadsem* temp_threadsem;
31
32 temp_threadsem = (os_thread*)g_freethreadsems;
33
34 if (temp_threadsem == NULL) return -1;
35
36 // pop a free thread from the list
37 g_freethreadsems = temp_threadsem->next;
38
39 // push the free thread on the used threads list
40 temp_threadsem->next = g_usedthreadsems;
41 g_usedthreadsems = temp_threadsem;
42
43 temp_threadsem->thread = thread;
44
45 return temp_threadsem;
46 }
47 void FreeThreadSem(os_threadsem* threadsem)
48 {
49 // threadsem should always equal g_usedthreadsem since its a queue
50
51 g_usedthreadsems = threadsem->next;
52
53 threadsem->next = g_freethreadsems;
54 g_freethreadsems = threadsem;
55 }
56
57 // return 1 if you had to wait at all
58 UCHAR WaitSemaphore(os_semaphore* semaphore)
59 {
60 register UCHAR ret;
61 os_threadsem *temp_threadsem;
62
63 #asm("cli");
64
65 ret = 1;
66
67 if (semaphore->remaining > 0)
68 {
69 --(semaphore->remaining);
70 ret = 0;
71 }
72 else
73 {
74 if (semaphore->queue != NULL)
75 {
76 // we have to wait
77 temp_threadsem = semaphore->queue;
78
79 while (temp_threadsem->next != NULL)
80 {
81 temp_threadsem = temp_threadsem->next;
82 }
83 temp_threadsem->next = CreateThreadSem(g_currthread);
84 }
85 else
86 {
87 semaphore->queue = CreateThreadSem(g_currthread);
88 }
89 g_currthread->state = THREADSTATE_BLOCKED;
90 os_schedule(0);
91 }
92
93 #asm("sei");
94
95 return ret;
96 }
97 void SignalSemaphore(os_semaphore* semaphore)
98 {
99 os_threadsem* temp_threadsem;
100
101 #asm("cli");
102
103 if (semaphore->queue == NULL)
104 {
105 ++semaphore->remaining;
106 }
107 else
108 {
109 // pop first in off
110 temp_threadsem = semaphore->queue;
111 semaphore->queue = temp_threadsem->next;
112
113 temp_threadsem->thread->state = THREADSTATE_RUNNING;
114
115 FreeThreadSem(temp_threadsem);
116 os_schedule(0);
117 }
118
119 #asm("sei");
120 }