Changeset 80649a91 in mainline
- Timestamp:
- 2006-05-21T19:28:37Z (19 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- a410beb
- Parents:
- 1ee11f4
- Files:
-
- 1 deleted
- 13 edited
- 5 moved
Legend:
- Unmodified
- Added
- Removed
-
Makefile
r1ee11f4 r80649a91 36 36 softint \ 37 37 softfloat \ 38 libadt \39 38 init \ 39 test \ 40 40 ns \ 41 41 fb -
fb/fb.c
r1ee11f4 r80649a91 45 45 46 46 #include <kernel/errno.h> 47 47 #include <async.h> 48 48 49 49 #include "fb.h" 50 51 52 53 #define pl /*printf("FB:L:%d\n",(int)__LINE__);*/54 50 55 51 #define EFB (-1) … … 80 76 81 77 82 83 84 int main(int argc, char *argv[]) 85 { 86 78 static int init_fb(void) 79 { 87 80 __address fb_ph_addr; 88 81 unsigned int fb_width; … … 92 85 __address fb_addr; 93 86 int a=0; 94 95 96 if(!sysinfo_value("fb")) return -1;97 87 int i,j,k; 88 int w; 89 char text[]="HelenOS Framebuffer driver\non Virtual Framebuffer\nVFB "; 90 98 91 fb_ph_addr=sysinfo_value("fb.address.physical"); 99 92 fb_width=sysinfo_value("fb.width"); … … 105 98 106 99 107 100 108 101 map_physmem(task_get_id(),(void *)((__address)fb_ph_addr),(void *)fb_addr, 109 (fb_scanline*fb_height+PAGE_SIZE-1)>>PAGE_WIDTH,1);102 (fb_scanline*fb_height+PAGE_SIZE-1)>>PAGE_WIDTH,1); 110 103 111 104 fb_init(0,fb_addr, fb_width, fb_height, fb_bpp, fb_scanline, … … 115 108 fb_putchar(0,' '); 116 109 117 118 { 119 int i,j; 120 121 for(i=0;i<H_NO_VFBS;i++) 122 for(j=0;j<V_NO_VFBS;j++) 123 { 124 125 int w=create_window(0,(fb_width/H_NO_VFBS)*i+SPACING, 126 (fb_height/V_NO_VFBS)*j+SPACING,(fb_width/H_NO_VFBS)-2*SPACING , 127 (fb_height/V_NO_VFBS)-2*SPACING,mod_col(DEFAULT_BGCOLOR,/*i+j*H_NO_VFBS*/0), 128 mod_col(DEFAULT_FGCOLOR,/*i+j*H_NO_VFBS*/0), 129 mod_col(DEFAULT_LOGOCOLOR,/*i+j*H_NO_VFBS)*/0)); 130 131 if(w==EFB) return -1; 132 133 { 134 char text[]="Hello, World from\nHelenOS Framebuffer driver\non Virtual Framebuffer\nVFB "; 135 int i; 136 for(i=0;text[i];i++) fb_putchar(w,text[i]); 137 fb_putchar(w,w+'0'); 138 fb_putchar(w,'\n'); 139 } 140 } 110 for(i=0;i<H_NO_VFBS;i++) 111 for(j=0;j<V_NO_VFBS;j++) { 112 w = create_window(0,(fb_width/H_NO_VFBS)*i+SPACING, 113 (fb_height/V_NO_VFBS)*j+SPACING,(fb_width/H_NO_VFBS)-2*SPACING , 114 (fb_height/V_NO_VFBS)-2*SPACING,mod_col(DEFAULT_BGCOLOR,/*i+j*H_NO_VFBS*/0), 115 mod_col(DEFAULT_FGCOLOR,/*i+j*H_NO_VFBS*/0), 116 mod_col(DEFAULT_LOGOCOLOR,/*i+j*H_NO_VFBS)*/0)); 117 118 if( w== EFB) 119 return -1; 120 121 for(k=0;text[k];k++) 122 fb_putchar(w,text[k]); 123 fb_putchar(w,w+'0'); 124 fb_putchar(w,'\n'); 125 } 126 return 0; 127 } 128 129 int vfb_no = 1; 130 void client_connection(ipc_callid_t iid, ipc_call_t *icall) 131 { 132 ipc_callid_t callid; 133 ipc_call_t call; 134 int vfb = vfb_no++; 135 136 if (vfb > 9) { 137 ipc_answer_fast(iid, ELIMIT, 0,0); 138 return; 141 139 } 142 143 140 ipc_answer_fast(iid, 0, 0, 0); 141 142 while (1) { 143 callid = async_get_call(&call); 144 switch (IPC_GET_METHOD(call)) { 145 case IPC_M_PHONE_HUNGUP: 146 ipc_answer_fast(callid,0,0,0); 147 return; /* Exit thread */ 148 149 case FB_PUTCHAR: 150 ipc_answer_fast(callid,0,0,0); 151 fb_putchar(vfb,IPC_GET_ARG2(call)); 152 break; 153 default: 154 ipc_answer_fast(callid,ENOENT,0,0); 155 } 156 } 157 } 158 159 int main(int argc, char *argv[]) 160 { 144 161 ipc_call_t call; 145 162 ipc_callid_t callid; … … 151 168 ipcarg_t retval, arg1, arg2; 152 169 170 if(!sysinfo_value("fb")) return -1; 153 171 154 172 155 173 if ((res = ipc_connect_to_me(PHONE_NS, SERVICE_VIDEO, 0, &phonead)) != 0) 156 {157 174 return -1; 158 }; 159 160 161 while (1) { 162 static int vfb_no=1; 163 164 callid = ipc_wait_for_call(&call); 165 // printf("%s:Call phone=%lX..", NAME, call.in_phone_hash); 166 switch (IPC_GET_METHOD(call)&((1<<METHOD_WIDTH)-1)) { 167 case IPC_M_PHONE_HUNGUP: 168 // fb_putchar(4,((a++)&15)+'A'); 169 170 retval = 0; 171 break; 172 case IPC_M_CONNECT_ME_TO: 173 retval = 0; 174 // fb_putchar(1,((a++)&15)+'A'); 175 break; 176 case FB_GET_VFB: 177 retval = 0; 178 arg1 = vfb_no++; 179 // fb_putchar(2,((a++)&15)+'A'); 180 181 break; 182 183 case FB_PUTCHAR: 184 retval = 0; 185 fb_putchar(IPC_GET_ARG1(call),IPC_GET_ARG2(call)); 186 // fb_putchar(2,((a++)&15)+'A'); 187 break; 188 189 default: 190 retval = ENOENT; 191 // fb_putchar(3,((a++)&15)+'A'); 192 break; 193 } 194 195 if (! (callid & IPC_CALLID_NOTIFICATION)) { 196 ipc_answer_fast(callid, retval, arg1, arg2); 197 } 198 } 199 175 176 init_fb(); 177 178 async_manager(); 179 /* Never reached */ 200 180 return 0; 201 181 } … … 310 290 FB(item,fbaddress)[startbyte + 0] = BLUE(color, 8); 311 291 #endif 312 313 292 314 293 } … … 372 351 for (y = 0; y < FB(item,yres); y++) 373 352 { 374 clear_line(item,y); pl353 clear_line(item,y); 375 354 } 376 355 } … … 554 533 555 534 556 FB(item,fbaddress) = (unsigned char *) addr; pl557 FB(item,xres) = x; pl558 FB(item,yres) = y; pl559 FB(item,scanline) = scan; pl560 561 562 FB(item,rows) = y / FONT_SCANLINES; pl563 FB(item,columns) = x / COL_WIDTH; pl535 FB(item,fbaddress) = (unsigned char *) addr; 536 FB(item,xres) = x; 537 FB(item,yres) = y; 538 FB(item,scanline) = scan; 539 540 541 FB(item,rows) = y / FONT_SCANLINES; 542 FB(item,columns) = x / COL_WIDTH; 564 543 565 544 FB(item,BGCOLOR)=BGCOLOR; … … 568 547 569 548 570 clear_screen(item); pl571 draw_logo(item,FB(item,xres) - helenos_width, 0); pl572 invert_cursor(item); pl549 clear_screen(item); 550 draw_logo(item,FB(item,xres) - helenos_width, 0); 551 invert_cursor(item); 573 552 574 553 } -
kbd/generic/kbd.c
r1ee11f4 r80649a91 37 37 #include <kbd.h> 38 38 #include <key_buffer.h> 39 #include < fifo.h>39 #include <libadt/fifo.h> 40 40 41 41 #define NAME "KBD" -
kbd/generic/key_buffer.c
r1ee11f4 r80649a91 28 28 29 29 #include <key_buffer.h> 30 #include < fifo.h>30 #include <libadt/fifo.h> 31 31 32 32 #define KBD_BUFFER_SIZE 128 /**< Size of buffer for pressed keys */ -
libc/Makefile
r1ee11f4 r80649a91 63 63 generic/psthread.c \ 64 64 generic/sysinfo.c \ 65 generic/ipc.c 65 generic/ipc.c \ 66 generic/async.c \ 67 generic/libadt/list.o \ 68 generic/libadt/hash_table.o 66 69 67 70 ARCH_SOURCES += \ … … 80 83 ln -sfn kernel/arch include/arch 81 84 ln -sfn ../arch/$(ARCH)/include include/libarch 82 ln -sfn ../../libadt/include include/libadt83 85 84 86 -include Makefile.depend 85 87 86 88 clean: 87 -rm -f include/kernel include/arch include/libarch include/libadtlibc.a arch/$(ARCH)/_link.ld Makefile.depend89 -rm -f include/kernel include/arch include/libarch libc.a arch/$(ARCH)/_link.ld Makefile.depend 88 90 find generic/ arch/$(ARCH)/ -name '*.o' -follow -exec rm \{\} \; 89 91 … … 92 94 93 95 libc.a: depend $(ARCH_OBJECTS) $(GENERIC_OBJECTS) 94 $(AR) rc libc.a $( ARCH_OBJECTS) $(GENERIC_OBJECTS)96 $(AR) rc libc.a $(LIBS) $(ARCH_OBJECTS) $(GENERIC_OBJECTS) 95 97 96 98 arch/$(ARCH)/_link.ld: arch/$(ARCH)/_link.ld.in -
libc/generic/async.c
r1ee11f4 r80649a91 27 27 */ 28 28 29 ipc_wait_t call_func(args) 30 { 31 } 32 33 ipc_wait_t fire_function(args) 34 { 35 stack = malloc(stacksize); 36 setup(stack); 37 add_to_list_of_ready_funcs(stack); 38 if (threads_waiting_for_message) 39 send_message_to_self_to_one_up(); 40 } 41 42 void discard_result(ipc_wait_t funcid) 43 { 44 } 45 46 int wait_result(ipc_wait_t funcid); 47 { 48 save_context(self); 49 restart: 50 if result_available() { 51 if in_list_of_ready(self): 52 tear_off_list(self); 53 return retval; 54 } 55 add_to_waitlist_of(funcid); 56 57 take_something_from_list_of_ready(); 58 if something { 59 60 restore_context(something); 61 } else { /* nothing */ 62 wait_for_call(); 63 if (answer) { 64 mark_result_ready(); 65 put_waiting_thread_to_waitlist(); 66 67 goto restart; 29 /** 30 * Asynchronous library 31 * 32 * The aim of this library is facilitating writing programs utilizing 33 * the asynchronous nature of Helenos IPC, yet using a normal way 34 * of programming. 35 * 36 * You should be able to write very simple multithreaded programs, 37 * the async framework will automatically take care of most synchronization 38 * problems. 39 * 40 * Default semantics: 41 * - send() - send asynchronously. If the kernel refuses to send more 42 * messages, [ try to get responses from kernel, if nothing 43 * found, might try synchronous ] 44 * 45 * Example of use: 46 * 47 * 1) Multithreaded client application 48 * create_thread(thread1); 49 * create_thread(thread2); 50 * ... 51 * 52 * thread1() { 53 * conn = ipc_connect_me_to(); 54 * c1 = send(conn); 55 * c2 = send(conn); 56 * wait_for(c1); 57 * wait_for(c2); 58 * } 59 * 60 * 61 * 2) Multithreaded server application 62 * main() { 63 * wait_for_connection(new_connection); 64 * } 65 * 66 * 67 * new_connection(int connection) { 68 * accept(connection); 69 * msg = get_msg(); 70 * handle(msg); 71 * answer(msg); 72 * 73 * msg = get_msg(); 74 * .... 75 * } 76 */ 77 #include <futex.h> 78 #include <async.h> 79 #include <psthread.h> 80 #include <stdio.h> 81 #include <libadt/hash_table.h> 82 #include <libadt/list.h> 83 #include <ipc/ipc.h> 84 #include <assert.h> 85 #include <errno.h> 86 87 static atomic_t conn_futex = FUTEX_INITIALIZER; 88 static hash_table_t conn_hash_table; 89 90 typedef struct { 91 link_t link; 92 ipc_callid_t callid; 93 ipc_call_t call; 94 } msg_t; 95 96 typedef struct { 97 link_t link; 98 ipcarg_t in_phone_hash; /**< Incoming phone hash. */ 99 link_t msg_queue; /**< Messages that should be delivered to this thread */ 100 pstid_t ptid; /**< Thread associated with this connection */ 101 int active; /**< If this thread is currently active */ 102 int opened; /* If the connection was accepted */ 103 /* Structures for connection opening packet */ 104 ipc_callid_t callid; 105 ipc_call_t call; 106 } connection_t; 107 108 __thread connection_t *PS_connection; 109 110 /* Hash table functions */ 111 112 #define ASYNC_HASH_TABLE_CHAINS 32 113 114 static hash_index_t conn_hash(unsigned long *key) 115 { 116 assert(key); 117 return ((*key) >> 4) % ASYNC_HASH_TABLE_CHAINS; 118 } 119 120 static int conn_compare(unsigned long key[], hash_count_t keys, link_t *item) 121 { 122 connection_t *hs; 123 124 hs = hash_table_get_instance(item, connection_t, link); 125 126 return key[0] == hs->in_phone_hash; 127 } 128 129 static void conn_remove(link_t *item) 130 { 131 free(hash_table_get_instance(item, connection_t, link)); 132 } 133 134 135 /** Operations for NS hash table. */ 136 static hash_table_operations_t conn_hash_table_ops = { 137 .hash = conn_hash, 138 .compare = conn_compare, 139 .remove_callback = conn_remove 140 }; 141 142 /** Try to route a call to an appropriate connection thread 143 * 144 */ 145 static int route_call(ipc_callid_t callid, ipc_call_t *call) 146 { 147 connection_t *conn; 148 msg_t *msg; 149 link_t *hlp; 150 unsigned long key; 151 152 futex_down(&conn_futex); 153 154 key = call->in_phone_hash; 155 hlp = hash_table_find(&conn_hash_table, &key); 156 if (!hlp) { 157 futex_up(&conn_futex); 158 return 0; 159 } 160 conn = hash_table_get_instance(hlp, connection_t, link); 161 162 msg = malloc(sizeof(*msg)); 163 msg->callid = callid; 164 msg->call = *call; 165 list_append(&msg->link, &conn->msg_queue); 166 167 if (!conn->active) { 168 conn->active = 1; 169 psthread_add_ready(conn->ptid); 170 } 171 172 futex_up(&conn_futex); 173 174 return 1; 175 } 176 177 ipc_callid_t async_get_call(ipc_call_t *call) 178 { 179 msg_t *msg; 180 ipc_callid_t callid; 181 connection_t *conn; 182 183 futex_down(&conn_futex); 184 185 conn = PS_connection; 186 /* If nothing in queue, wait until something appears */ 187 if (list_empty(&conn->msg_queue)) { 188 conn->active = 0; 189 psthread_schedule_next_adv(PS_TO_MANAGER); 190 } 191 192 msg = list_get_instance(conn->msg_queue.next, msg_t, link); 193 list_remove(&msg->link); 194 callid = msg->callid; 195 *call = msg->call; 196 free(msg); 197 198 futex_up(&conn_futex); 199 return callid; 200 } 201 202 void client_connection(ipc_callid_t callid, ipc_call_t *call) 203 { 204 printf("Got connection - no handler.\n"); 205 _exit(1); 206 } 207 208 static int connection_thread(void *arg) 209 { 210 /* Setup thread local connection pointer */ 211 PS_connection = (connection_t *)arg; 212 client_connection(PS_connection->callid, &PS_connection->call); 213 214 futex_down(&conn_futex); 215 /* TODO: remove myself from connection hash table */ 216 futex_up(&conn_futex); 217 /* TODO: answer all unanswered messages in queue with 218 * EHANGUP */ 219 } 220 221 /** Create new thread for a new connection 222 * 223 * Creates new thread for connection, fills in connection 224 * structures and inserts it into the hash table, so that 225 * later we can easily do routing of messages to particular 226 * threads. 227 */ 228 static void new_connection(ipc_callid_t callid, ipc_call_t *call) 229 { 230 pstid_t ptid; 231 connection_t *conn; 232 unsigned long key; 233 234 conn = malloc(sizeof(*conn)); 235 if (!conn) { 236 ipc_answer_fast(callid, ENOMEM, 0, 0); 237 return; 238 } 239 conn->in_phone_hash = IPC_GET_ARG3(*call); 240 list_initialize(&conn->msg_queue); 241 conn->opened = 0; 242 conn->ptid = psthread_create(connection_thread, conn); 243 conn->callid = callid; 244 conn->call = *call; 245 conn->active = 1; /* We will activate it asap */ 246 list_initialize(&conn->link); 247 if (!conn->ptid) { 248 free(conn); 249 ipc_answer_fast(callid, ENOMEM, 0, 0); 250 return; 251 } 252 key = conn->in_phone_hash; 253 futex_down(&conn_futex); 254 /* Add connection to hash table */ 255 hash_table_insert(&conn_hash_table, &key, &conn->link); 256 futex_up(&conn_futex); 257 258 psthread_add_ready(conn->ptid); 259 } 260 261 /** Handle call to a task */ 262 static void handle_call(ipc_callid_t callid, ipc_call_t *call) 263 { 264 if (route_call(callid, call)) 265 return; 266 267 switch (IPC_GET_METHOD(*call)) { 268 case IPC_M_INTERRUPT: 269 break; 270 case IPC_M_CONNECT_ME_TO: 271 /* Open new connection with thread etc. */ 272 new_connection(callid, call); 273 break; 274 default: 275 ipc_answer_fast(callid, EHANGUP, 0, 0); 276 } 277 } 278 279 /** Endless loop dispatching incoming calls and answers */ 280 int async_manager() 281 { 282 ipc_call_t call; 283 ipc_callid_t callid; 284 285 while (1) { 286 if (psthread_schedule_next_adv(PS_FROM_MANAGER)) { 287 futex_up(&conn_futex); /* conn_futex is always held 288 * when entering manager thread 289 */ 290 continue; 68 291 } 69 } 70 71 } 72 73 74 int ipc_call_sync(args) 75 { 76 return ipc_wait(call_func(args)); 77 } 292 callid = ipc_wait_cycle(&call,SYNCH_NO_TIMEOUT,SYNCH_BLOCKING); 293 294 if (callid & IPC_CALLID_ANSWERED) 295 continue; 296 handle_call(callid, &call); 297 } 298 } 299 300 static int async_manager_thread(void *arg) 301 { 302 futex_up(&conn_futex); /* conn_futex is always locked when entering 303 * manager */ 304 async_manager(); 305 } 306 307 /** Add one manager to manager list */ 308 void async_create_manager(void) 309 { 310 pstid_t ptid; 311 312 ptid = psthread_create(async_manager_thread, NULL); 313 psthread_add_manager(ptid); 314 } 315 316 /** Remove one manager from manager list */ 317 void async_destroy_manager(void) 318 { 319 psthread_remove_manager(); 320 } 321 322 /** Initialize internal structures needed for async manager */ 323 int _async_init(void) 324 { 325 if (!hash_table_create(&conn_hash_table, ASYNC_HASH_TABLE_CHAINS, 1, &conn_hash_table_ops)) { 326 printf("%s: cannot create hash table\n", "async"); 327 return ENOMEM; 328 } 329 330 } -
libc/generic/ipc.c
r1ee11f4 r80649a91 58 58 LIST_INITIALIZE(queued_calls); 59 59 60 static atomic_t ipc_futex; 61 62 void _ipc_init(void) 63 { 64 futex_initialize(&ipc_futex, 1); 65 } 60 static atomic_t ipc_futex = FUTEX_INITIALIZER; 66 61 67 62 int ipc_call_sync(int phoneid, ipcarg_t method, ipcarg_t arg1, … … 253 248 254 249 255 /** Unconditionally wait for an IPC call.250 /** One cycle of ipc wait for call call 256 251 * 257 252 * - dispatch ASYNC reoutines in the background 258 253 * @param call Space where the message is stored 254 * @param usec Timeout in microseconds 255 * @param flags Flags passed to SYS_IPC_WAIT (blocking, nonblocking) 259 256 * @return Callid of the answer. 260 257 */ 261 ipc_callid_t ipc_wait_for_call(ipc_call_t *call) 262 { 263 ipc_callid_t callid; 264 265 do { 266 try_dispatch_queued_calls(); 267 268 callid = __SYSCALL3(SYS_IPC_WAIT, (sysarg_t) call, SYNCH_NO_TIMEOUT, SYNCH_BLOCKING); 269 /* Handle received answers */ 270 if (callid & IPC_CALLID_ANSWERED) 271 handle_answer(callid, call); 272 } while (callid & IPC_CALLID_ANSWERED); 258 ipc_callid_t ipc_wait_cycle(ipc_call_t *call, uint32_t usec, int flags) 259 { 260 ipc_callid_t callid; 261 262 try_dispatch_queued_calls(); 263 264 callid = __SYSCALL3(SYS_IPC_WAIT, (sysarg_t) call, usec, flags); 265 /* Handle received answers */ 266 if (callid & IPC_CALLID_ANSWERED) 267 handle_answer(callid, call); 273 268 274 269 return callid; … … 287 282 288 283 do { 289 try_dispatch_queued_calls(); 290 291 callid = __SYSCALL3(SYS_IPC_WAIT, (sysarg_t) call, usec, SYNCH_BLOCKING); 292 /* Handle received answers */ 293 if (callid & IPC_CALLID_ANSWERED) 294 handle_answer(callid, call); 284 callid = ipc_wait_cycle(call, usec, SYNCH_BLOCKING); 295 285 } while (callid & IPC_CALLID_ANSWERED); 296 286 … … 309 299 310 300 do { 311 try_dispatch_queued_calls(); 312 313 callid = __SYSCALL3(SYS_IPC_WAIT, (sysarg_t)call, SYNCH_NO_TIMEOUT, SYNCH_NON_BLOCKING); 314 /* Handle received answers */ 315 if (callid & IPC_CALLID_ANSWERED) 316 handle_answer(callid, call); 301 callid = ipc_wait_cycle(call, SYNCH_NO_TIMEOUT, SYNCH_NON_BLOCKING); 317 302 } while (callid & IPC_CALLID_ANSWERED); 318 303 -
libc/generic/libadt/hash_table.c
r1ee11f4 r80649a91 31 31 */ 32 32 33 #include < hash_table.h>34 #include <li st.h>33 #include <libadt/hash_table.h> 34 #include <libadt/list.h> 35 35 #include <unistd.h> 36 36 #include <malloc.h> -
libc/generic/libadt/list.c
r1ee11f4 r80649a91 27 27 */ 28 28 29 #include <li st.h>29 #include <libadt/list.h> 30 30 31 31 -
libc/generic/libc.c
r1ee11f4 r80649a91 34 34 #include <io/stream.h> 35 35 #include <ipc/ipc.h> 36 #include <async.h> 36 37 37 38 void _exit(int status) { … … 40 41 41 42 void __main(void) { 42 tcb_t *tcb; 43 44 tcb = __make_tls(); 45 __tcb_set(tcb); 46 psthread_setup(tcb); 47 _ipc_init(); 43 psthread_data_t *pt; 44 45 _async_init(); 46 pt = psthread_setup(); 47 __tcb_set(pt->tcb); 48 48 } 49 49 … … 55 55 56 56 void __exit(void) { 57 tcb_t *tcb; 58 59 tcb = __tcb_get(); 60 psthread_teardown(tcb->pst_data); 61 __free_tls(tcb); 57 psthread_teardown(__tcb_get()->pst_data); 62 58 _exit(0); 63 59 } -
libc/generic/psthread.c
r1ee11f4 r80649a91 34 34 #include <stdio.h> 35 35 #include <kernel/arch/faddr.h> 36 36 #include <futex.h> 37 #include <assert.h> 37 38 38 39 #ifndef PSTHREAD_INITIAL_STACK_PAGES_NO … … 41 42 42 43 static LIST_INITIALIZE(ready_list); 44 static LIST_INITIALIZE(manager_list); 43 45 44 46 static void psthread_exit(void) __attribute__ ((noinline)); 45 47 static void psthread_main(void); 46 48 49 static atomic_t psthread_futex = FUTEX_INITIALIZER; 50 47 51 /** Setup PSthread information into TCB structure */ 48 psthread_data_t * psthread_setup(tcb_t *tcb) 49 { 50 psthread_data_t *pt; 52 psthread_data_t * psthread_setup() 53 { 54 psthread_data_t *pt; 55 tcb_t *tcb; 56 57 tcb = __make_tls(); 58 if (!tcb) 59 return NULL; 51 60 52 61 pt = malloc(sizeof(*pt)); 53 62 if (!pt) { 63 __free_tls(tcb); 54 64 return NULL; 55 65 } … … 63 73 void psthread_teardown(psthread_data_t *pt) 64 74 { 75 __free_tls(pt->tcb); 65 76 free(pt); 66 77 } … … 73 84 psthread_data_t *pt; 74 85 75 if (list_empty(&ready_list)) { 76 /* Wait on IPC queue etc... */ 77 printf("Cannot exit!!!\n"); 86 futex_down(&psthread_futex); 87 88 if (!list_empty(&ready_list)) 89 pt = list_get_instance(ready_list.next, psthread_data_t, link); 90 else if (!list_empty(&manager_list)) 91 pt = list_get_instance(manager_list.next, psthread_data_t, link); 92 else { 93 printf("Cannot find suitable psthread to run.\n"); 78 94 _exit(0); 79 95 } 80 pt = list_get_instance(ready_list.next, psthread_data_t, link);81 96 list_remove(&pt->link); 97 futex_up(&psthread_futex); 98 82 99 context_restore(&pt->ctx); 100 /* Never reached */ 83 101 } 84 102 … … 99 117 /** Schedule next userspace pseudo thread. 100 118 * 119 * @param tomanager If true, we are switching to next ready manager thread 120 * (if none is found, thread is exited) 121 * @param frommanager If true, we are switching from manager thread 101 122 * @return 0 if there is no ready pseudo thread, 1 otherwise. 102 123 */ 103 int psthread_schedule_next(void) 104 { 105 psthread_data_t *pt; 106 107 if (list_empty(&ready_list)) 108 return 0; 124 int psthread_schedule_next_adv(pschange_type ctype) 125 { 126 psthread_data_t *pt; 127 int retval = 0; 128 129 futex_down(&psthread_futex); 130 131 if (ctype == PS_PREEMPT && list_empty(&ready_list)) 132 goto ret_0; 133 134 if (ctype == PS_FROM_MANAGER && list_empty(&ready_list)) { 135 goto ret_0; 136 } 137 assert(!(ctype == PS_TO_MANAGER && list_empty(&manager_list))); 109 138 110 139 pt = __tcb_get()->pst_data; 111 if (!context_save(&pt->ctx)) 112 return 1; 140 if (!context_save(&pt->ctx)) 141 return 1; // futex_up already done here 142 143 if (ctype == PS_PREEMPT) 144 list_append(&pt->link, &ready_list); 145 else if (ctype == PS_FROM_MANAGER) 146 list_append(&pt->link, &manager_list); 113 147 114 list_append(&pt->link, &ready_list); 115 pt = list_get_instance(ready_list.next, psthread_data_t, link); 148 if (ctype == PS_TO_MANAGER) 149 pt = list_get_instance(manager_list.next,psthread_data_t, link); 150 else 151 pt = list_get_instance(ready_list.next, psthread_data_t, link); 116 152 list_remove(&pt->link); 117 153 154 futex_up(&psthread_futex); 118 155 context_restore(&pt->ctx); 156 157 ret_0: 158 futex_up(&psthread_futex); 159 return retval; 119 160 } 120 161 … … 143 184 144 185 free(pt->stack); 145 __free_tls(pt->tcb);146 186 psthread_teardown((void *)pt); 147 187 … … 150 190 151 191 /** 152 * Create a userspace thread and append it to ready list.192 * Create a userspace thread 153 193 * 154 194 * @param func Pseudo thread function. … … 160 200 { 161 201 psthread_data_t *pt; 162 tcb_t *tcb; 163 164 tcb = __make_tls(); 165 if (!tcb) 202 203 pt = psthread_setup(); 204 if (!pt) 166 205 return 0; 167 168 pt = psthread_setup(tcb);169 if (!pt) {170 __free_tls(tcb);171 return 0;172 }173 206 pt->stack = (char *) malloc(PSTHREAD_INITIAL_STACK_PAGES_NO*getpagesize()); 174 207 175 208 if (!pt->stack) { 176 __free_tls(tcb);177 209 psthread_teardown(pt); 178 210 return 0; … … 186 218 context_save(&pt->ctx); 187 219 context_set(&pt->ctx, FADDR(psthread_main), pt->stack, PSTHREAD_INITIAL_STACK_PAGES_NO*getpagesize(), 188 tcb); 189 220 pt->tcb); 221 222 return (pstid_t )pt; 223 } 224 225 /** Add a thread to ready list */ 226 void psthread_add_ready(pstid_t psthrid) 227 { 228 psthread_data_t *pt; 229 230 pt = (psthread_data_t *) psthrid; 231 futex_down(&psthread_futex); 190 232 list_append(&pt->link, &ready_list); 191 192 return (pstid_t )pt; 193 } 233 futex_up(&psthread_futex); 234 } 235 236 /** Add a thread to manager list */ 237 void psthread_add_manager(pstid_t psthrid) 238 { 239 psthread_data_t *pt; 240 241 pt = (psthread_data_t *) psthrid; 242 243 futex_down(&psthread_futex); 244 list_append(&pt->link, &manager_list); 245 futex_up(&psthread_futex); 246 } 247 248 /** Remove one manager from manager list */ 249 void psthread_remove_manager() 250 { 251 futex_down(&psthread_futex); 252 if (list_empty(&manager_list)) { 253 printf("No manager found!.\n"); 254 futex_up(&psthread_futex); 255 return; 256 } 257 list_remove(manager_list.next); 258 futex_up(&psthread_futex); 259 } -
libc/generic/thread.c
r1ee11f4 r80649a91 34 34 #include <psthread.h> 35 35 #include <string.h> 36 #include <async.h> 36 37 37 38 #include <stdio.h> … … 81 82 * 82 83 * @param uarg Pointer to userspace argument structure. 84 * 85 * TODO: Thread stack pages memory leak 83 86 */ 84 87 void __thread_main(uspace_arg_t *uarg) 85 88 { 86 tcb_t *tcb; 87 /* This should initialize the area according to TLS specicification */ 88 tcb = __make_tls(); 89 __tcb_set(tcb); 90 psthread_setup(tcb); 89 psthread_data_t *pt; 90 91 pt = psthread_setup(); 92 __tcb_set(pt->tcb); 93 94 async_create_manager(); 91 95 92 96 uarg->uspace_thread_function(uarg->uspace_thread_arg); … … 94 98 free(uarg); 95 99 96 psthread_teardown(tcb->pst_data);97 __free_tls(tcb);100 async_destroy_manager(); 101 psthread_teardown(pt); 98 102 99 103 thread_exit(0); -
libc/include/ipc/ipc.h
r1ee11f4 r80649a91 34 34 #include <libc.h> 35 35 #include <types.h> 36 #include <kernel/synch/synch.h> 36 37 37 38 typedef sysarg_t ipcarg_t; … … 54 55 extern int ipc_call_sync(int phoneid, ipcarg_t method, ipcarg_t arg1, 55 56 ipcarg_t *result); 56 extern ipc_callid_t ipc_wait_ for_call(ipc_call_t *data);57 extern ipc_callid_t ipc_wait_cycle(ipc_call_t *call, uint32_t usec, int flags); 57 58 extern ipc_callid_t ipc_wait_for_call_timeout(ipc_call_t *data, uint32_t usec); 59 static inline ipc_callid_t ipc_wait_for_call(ipc_call_t *data) 60 { 61 return ipc_wait_for_call_timeout(data, SYNCH_NO_TIMEOUT); 62 } 58 63 extern ipc_callid_t ipc_trywait_for_call(ipc_call_t *data); 59 64 … … 72 77 extern int ipc_unregister_irq(int irq); 73 78 extern int ipc_forward_fast(ipc_callid_t callid, int phoneid, int method, ipcarg_t arg1); 74 extern void _ipc_init(void);75 79 76 80 #endif -
libc/include/psthread.h
r1ee11f4 r80649a91 41 41 #endif /* context_set */ 42 42 43 typedef enum { 44 PS_TO_MANAGER, 45 PS_FROM_MANAGER, 46 PS_PREEMPT 47 } pschange_type; 48 43 49 typedef sysarg_t pstid_t; 44 50 … … 62 68 63 69 pstid_t psthread_create(int (*func)(void *), void *arg); 64 int psthread_schedule_next(void);65 70 int psthread_join(pstid_t psthrid); 66 psthread_data_t * psthread_setup( tcb_t *tcb);71 psthread_data_t * psthread_setup(void); 67 72 void psthread_teardown(psthread_data_t *pt); 73 int psthread_schedule_next_adv(pschange_type ctype); 74 void psthread_add_ready(pstid_t ptid); 75 void psthread_add_manager(pstid_t psthrid); 76 void psthread_remove_manager(void); 77 78 static inline int psthread_schedule_next() { 79 return psthread_schedule_next_adv(PS_PREEMPT); 80 } 68 81 69 82 -
ns/Makefile
r1ee11f4 r80649a91 31 31 32 32 LIBC_PREFIX = ../libc 33 LIBADT_PREFIX = ../libadt34 33 SOFTINT_PREFIX = ../softint 35 34 include $(LIBC_PREFIX)/Makefile.toolchain 36 35 37 LIBS = $(LIB ADT_PREFIX)/libadt.a $(LIBC_PREFIX)/libc.a36 LIBS = $(LIBC_PREFIX)/libc.a 38 37 39 38 ## Sources
Note:
See TracChangeset
for help on using the changeset viewer.