Improved networking stability and thread safety.
[planlOS.git] / system / kernel / lwip / arch / sys_arch.c
blobab39f89d8763e88df0a354468273fc805f935b98
2 #include "arch/cc.h"
3 #include "ke/panic.h"
4 #include "ke/debug.h"
5 #include "lwip/sys.h"
7 KeSpinlock critlock;
9 void sys_init(void)
11 keInitSpinlock(&critlock);
14 void LWIP_PLATFORM_ASSERT(char *msg)
16 kePrint("%s\n", msg);
17 kePanic(0, 42);
21 sys_sem_t sys_sem_new(u8_t count)
23 sys_sem_t sem = malloc(sizeof(KeSpinlock));
24 keInitSpinlock(sem);
25 if (count) keLockSpinlock(sem);
26 return sem;
28 void sys_sem_free(sys_sem_t sem)
30 free(sem);
32 void sys_sem_signal(sys_sem_t sem)
34 keUnlockSpinlock(sem);
36 u32_t sys_arch_sem_wait(sys_sem_t sem, u32_t timeout)
38 if (!timeout)
40 uint64_t starttime = keGetTime();
41 keLockSpinlock(sem);
42 uint64_t needed = keGetTime() - starttime;
43 return needed / 1000;
45 else
47 uint64_t starttime = keGetTime();
48 uint64_t currenttime = starttime;
51 if (!keTryLockSpinlock(sem))
53 return (currenttime - starttime) / 1000;
55 currenttime = keGetTime();
57 while (currenttime - starttime < timeout * 1000);
58 return SYS_ARCH_TIMEOUT;
62 sys_mbox_t sys_mbox_new(int size)
64 struct sys_mbox *mbox = malloc(sizeof(struct sys_mbox));
65 keInitSpinlock(&mbox->lock);
66 mbox->firstentry = 0;
67 return mbox;
69 void sys_mbox_post(sys_mbox_t mbox, void *msg)
71 KeExecLevel oldlevel = keSetExecutionLevel(KE_LEVEL_HIGH);
72 keLockSpinlock(&mbox->lock);
73 sys_mbox_entry_t *entry = malloc(sizeof(sys_mbox_entry_t));
74 entry->data = msg;
75 entry->next = 0;
76 if (!mbox->firstentry)
78 mbox->firstentry = entry;
80 else
82 sys_mbox_entry_t *prev = mbox->firstentry;
83 while (prev->next) prev = prev->next;
84 prev->next = entry;
86 keUnlockSpinlock(&mbox->lock);
87 keSetExecutionLevel(oldlevel);
89 err_t sys_mbox_trypost(sys_mbox_t mbox, void *msg)
91 sys_mbox_post(mbox, msg);
92 return ERR_OK;
94 u32_t sys_arch_mbox_fetch(sys_mbox_t mbox, void **msg, u32_t timeout)
96 if (!timeout)
98 uint64_t starttime = keGetTime();
99 while (sys_arch_mbox_tryfetch(mbox, msg) != 0);
100 uint64_t needed = keGetTime() - starttime;
101 return needed / 1000;
103 else
105 uint64_t starttime = keGetTime();
106 uint64_t currenttime = starttime;
109 if (sys_arch_mbox_tryfetch(mbox, msg) == 0)
111 return (currenttime - starttime) / 1000;
113 asm volatile("int $0x32");
114 currenttime = keGetTime();
116 while (currenttime - starttime < timeout * 1000);
117 return SYS_ARCH_TIMEOUT;
120 u32_t sys_arch_mbox_tryfetch(sys_mbox_t mbox, void **msg)
122 KeExecLevel oldlevel = keSetExecutionLevel(KE_LEVEL_HIGH);
123 keLockSpinlock(&mbox->lock);
124 u32_t status = SYS_MBOX_EMPTY;
125 if (mbox->firstentry)
127 sys_mbox_entry_t *entry = mbox->firstentry;
128 mbox->firstentry = entry->next;
129 *msg = entry->data;
130 free(entry);
131 status = 0;
133 keUnlockSpinlock(&mbox->lock);
134 keSetExecutionLevel(oldlevel);
135 return status;
137 void sys_mbox_free(sys_mbox_t mbox)
139 KeExecLevel oldlevel = keSetExecutionLevel(KE_LEVEL_HIGH);
140 keLockSpinlock(&mbox->lock);
141 if (mbox->firstentry)
143 kePrint("Trying to free full mailbox.\n");
145 free(mbox);
146 keSetExecutionLevel(oldlevel);
149 sys_prot_t sys_arch_protect(void)
151 KeExecLevel oldlevel = keSetExecutionLevel(KE_LEVEL_HIGH);
152 return oldlevel;
154 void sys_arch_unprotect(sys_prot_t p)
156 keSetExecutionLevel(p);
159 static struct sys_timeouts deftimeouts;
161 static KeSpinlock threadlock;
162 static sys_thread_t *threads = 0;
163 static uint32_t threadcount = 0;
165 sys_thread_t sys_thread_new(char *name, void (*func)(void *arg), void *arg, int stacksize, int prio)
167 kePrint("Creeating thread %s\n", name);
168 // Create thread struct
169 sys_thread_t thread = malloc(sizeof(struct sys_thread));
170 memset(thread, 0, sizeof(struct sys_thread));
171 thread->name = name;
172 // Add to list
173 KeExecLevel oldlevel = keSetExecutionLevel(KE_LEVEL_HIGH);
174 keLockSpinlock(&threadlock);
175 threads = realloc(threads, (threadcount + 1) * sizeof(sys_thread_t));
176 threads[threadcount] = thread;
177 threadcount++;
178 keUnlockSpinlock(&threadlock);
179 keSetExecutionLevel(oldlevel);
180 // Start thread
181 keCreateKernelThread((uintptr_t)func, 1, arg);
182 return thread;
185 struct sys_timeouts *sys_arch_timeouts(void)
187 KeExecLevel oldlevel = keSetExecutionLevel(KE_LEVEL_HIGH);
188 KeThread *currentthread = keGetCurrentCPU()->currentthread;
189 keLockSpinlock(&threadlock);
190 struct sys_timeouts *timeouts = &deftimeouts;
191 uint32_t i;
192 for (i = 0; i < threadcount; i++)
194 if (threads[i]->thread == currentthread)
196 timeouts = &threads[i]->timeouts;
199 keUnlockSpinlock(&threadlock);
200 keSetExecutionLevel(oldlevel);
201 return timeouts;