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   }