- Timestamp:
- 2006-06-06T15:16:08Z (19 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- 63bb83e
- Parents:
- d7eafd8
- Location:
- libc
- Files:
-
- 7 edited
-
generic/async.c (modified) (15 diffs)
-
generic/io/stream.c (modified) (4 diffs)
-
generic/ipc.c (modified) (1 diff)
-
generic/psthread.c (modified) (11 diffs)
-
include/async.h (modified) (4 diffs)
-
include/ipc/ipc.h (modified) (1 diff)
-
include/psthread.h (modified) (2 diffs)
Legend:
- Unmodified
- Added
- Removed
-
libc/generic/async.c
rd7eafd8 r085bd54 135 135 } connection_t; 136 136 137 137 /** Identifier of incoming connection handled by current thread */ 138 138 __thread connection_t *PS_connection; 139 /** If true, it is forbidden to use async_req functions and 140 * all preemption is disabled */ 141 __thread int in_interrupt_handler; 139 142 140 143 static void default_client_connection(ipc_callid_t callid, ipc_call_t *call); … … 226 229 227 230 wd->timedout = 0; 231 wd->inlist = 1; 228 232 229 233 tmp = timeout_list.next; … … 295 299 conn = PS_connection; 296 300 297 if (usecs < 0) /* TODO: let it get through the ipc_call once */298 return 0;299 300 301 futex_down(&async_futex); 301 302 … … 308 309 /* If nothing in queue, wait until something appears */ 309 310 while (list_empty(&conn->msg_queue)) { 310 if (usecs) { 311 conn->wdata.inlist = 1; 311 if (usecs) 312 312 insert_timeout(&conn->wdata); 313 } 313 314 314 conn->wdata.active = 0; 315 315 psthread_schedule_next_adv(PS_TO_MANAGER); … … 363 363 PS_connection = (connection_t *)arg; 364 364 PS_connection->cthread(PS_connection->callid, &PS_connection->call); 365 366 365 /* Remove myself from connection hash table */ 367 366 futex_down(&async_futex); … … 436 435 switch (IPC_GET_METHOD(*call)) { 437 436 case IPC_M_INTERRUPT: 437 in_interrupt_handler = 1; 438 438 (*interrupt_received)(callid,call); 439 in_interrupt_handler = 0; 439 440 return; 440 441 case IPC_M_CONNECT_ME_TO: … … 486 487 487 488 /** Endless loop dispatching incoming calls and answers */ 488 int async_manager(void)489 static int async_manager_worker(void) 489 490 { 490 491 ipc_call_t call; … … 522 523 } 523 524 524 if (callid & IPC_CALLID_ANSWERED) 525 if (callid & IPC_CALLID_ANSWERED) { 525 526 continue; 527 } 526 528 527 529 handle_call(callid, &call); … … 538 540 static int async_manager_thread(void *arg) 539 541 { 542 in_interrupt_handler = 0; // TODO: Handle TLS better 540 543 futex_up(&async_futex); /* async_futex is always locked when entering 541 544 * manager */ 542 async_manager ();545 async_manager_worker(); 543 546 } 544 547 … … 608 611 amsg_t *msg; 609 612 613 if (in_interrupt_handler) { 614 printf("Cannot send asynchronou request in interrupt handler.\n"); 615 _exit(1); 616 } 617 610 618 msg = malloc(sizeof(*msg)); 611 619 msg->done = 0; … … 628 636 { 629 637 amsg_t *msg; 638 639 if (in_interrupt_handler) { 640 printf("Cannot send asynchronou request in interrupt handler.\n"); 641 _exit(1); 642 } 630 643 631 644 msg = malloc(sizeof(*msg)); … … 699 712 msg->wdata.ptid = psthread_get_id(); 700 713 msg->wdata.active = 0; 701 msg->wdata.inlist = 1;702 703 714 insert_timeout(&msg->wdata); 704 715 … … 726 737 amsg_t *msg; 727 738 739 if (in_interrupt_handler) { 740 printf("Cannot call async_usleep in interrupt handler.\n"); 741 _exit(1); 742 } 743 728 744 msg = malloc(sizeof(*msg)); 729 745 if (!msg) … … 731 747 732 748 msg->wdata.ptid = psthread_get_id(); 733 msg->wdata.inlist = 1;734 749 msg->wdata.active = 0; 735 750 … … 757 772 interrupt_received = conn; 758 773 } 774 775 /* Primitive functions for simple communication */ 776 void async_msg_3(int phoneid, ipcarg_t method, ipcarg_t arg1, 777 ipcarg_t arg2, ipcarg_t arg3) 778 { 779 ipc_call_async_3(phoneid, method, arg1, arg2, arg3, NULL, NULL, !in_interrupt_handler); 780 } 781 782 void async_msg_2(int phoneid, ipcarg_t method, ipcarg_t arg1, ipcarg_t arg2) 783 { 784 ipc_call_async_2(phoneid, method, arg1, arg2, NULL, NULL, !in_interrupt_handler); 785 } -
libc/generic/io/stream.c
rd7eafd8 r085bd54 65 65 66 66 while (i < count) { 67 if ( sync_send_2(streams[0].phone, CONSOLE_GETCHAR, 0, 0, &r0, &r1) < 0) {67 if (async_req_2(streams[0].phone, CONSOLE_GETCHAR, 0, 0, &r0, &r1) < 0) { 68 68 return -1; 69 69 } … … 79 79 80 80 for (i = 0; i < count; i++) 81 send_call(streams[1].phone, CONSOLE_PUTCHAR, ((const char *)buf)[i]);81 async_msg(streams[1].phone, CONSOLE_PUTCHAR, ((const char *)buf)[i]); 82 82 83 83 return count; … … 131 131 { 132 132 int c = 0; 133 133 134 134 while (((streams[c].w) || (streams[c].r)) && (c < FDS)) 135 135 c++; … … 160 160 ssize_t write(int fd, const void *buf, size_t count) 161 161 { 162 // __SYSCALL3(SYS_IO, 1, (sysarg_t)buf, (sysarg_t) count); 163 // return count; 162 164 if (fd < FDS) 163 165 return streams[fd].w(streams[fd].param, buf, count); -
libc/generic/ipc.c
rd7eafd8 r085bd54 438 438 } 439 439 440 /* Primitive functions for simple communication */441 void send_call_3(int phoneid, ipcarg_t method, ipcarg_t arg1,442 ipcarg_t arg2, ipcarg_t arg3)443 {444 ipc_call_async_3(phoneid, method, arg1, arg2, arg3, NULL, NULL, 1);445 }446 447 void send_call_2(int phoneid, ipcarg_t method, ipcarg_t arg1, ipcarg_t arg2)448 {449 ipc_call_async_2(phoneid, method, arg1, arg2, NULL, NULL, 1);450 }451 452 void nsend_call_3(int phoneid, ipcarg_t method, ipcarg_t arg1,453 ipcarg_t arg2, ipcarg_t arg3)454 {455 ipc_call_async_3(phoneid, method, arg1, arg2, arg3, NULL, NULL, 0);456 }457 458 void nsend_call_2(int phoneid, ipcarg_t method, ipcarg_t arg1, ipcarg_t arg2)459 {460 ipc_call_async_2(phoneid, method, arg1, arg2, NULL, NULL, 0);461 }462 -
libc/generic/psthread.c
rd7eafd8 r085bd54 43 43 44 44 static LIST_INITIALIZE(ready_list); 45 static LIST_INITIALIZE(serialized_list); 45 46 static LIST_INITIALIZE(manager_list); 46 47 … … 49 50 50 51 static atomic_t psthread_futex = FUTEX_INITIALIZER; 52 /** Count of real threads that are in async_serialized mode */ 53 static int serialized_threads; /* Protected by async_futex */ 54 /** Thread-local count of serialization. If >0, we must not preempt */ 55 static __thread serialization_count; 56 /** Counter of threads residing in async_manager */ 57 static int threads_in_manager; 51 58 52 59 /** Setup PSthread information into TCB structure */ … … 78 85 } 79 86 80 /** Function to preempt to other pseudo thread without adding81 * currently running pseudo thread to ready_list.82 */83 void psthread_exit(void)84 {85 psthread_data_t *pt;86 87 futex_down(&psthread_futex);88 89 if (!list_empty(&ready_list))90 pt = list_get_instance(ready_list.next, psthread_data_t, link);91 else if (!list_empty(&manager_list))92 pt = list_get_instance(manager_list.next, psthread_data_t, link);93 else {94 printf("Cannot find suitable psthread to run.\n");95 _exit(0);96 }97 list_remove(&pt->link);98 futex_up(&psthread_futex);99 100 context_restore(&pt->ctx);101 /* Never reached */102 }103 104 87 /** Function that is called on entry to new uspace thread */ 105 88 void psthread_main(void) … … 107 90 psthread_data_t *pt = __tcb_get()->pst_data; 108 91 92 serialization_count = 0; // TODO: WHY HERE? 109 93 pt->retval = pt->func(pt->arg); 110 94 … … 113 97 list_append(&pt->waiter->link, &ready_list); 114 98 115 psthread_ exit();99 psthread_schedule_next_adv(PS_FROM_DEAD); 116 100 } 117 101 … … 128 112 int psthread_schedule_next_adv(pschange_type ctype) 129 113 { 130 psthread_data_t * pt;114 psthread_data_t *srcpt, *dstpt; 131 115 int retval = 0; 132 116 … … 136 120 goto ret_0; 137 121 138 if (ctype == PS_FROM_MANAGER && list_empty(&ready_list)) { 139 goto ret_0; 122 if (ctype == PS_FROM_MANAGER) { 123 if (list_empty(&ready_list) && list_empty(&serialized_list)) 124 goto ret_0; 125 /* Do not preempt if there is not sufficient count of thread managers */ 126 if (list_empty(&serialized_list) && threads_in_manager <= serialized_threads) { 127 goto ret_0; 128 } 140 129 } 141 130 /* If we are going to manager and none exists, create it */ 142 while (ctype == PS_TO_MANAGER && list_empty(&manager_list)) { 143 futex_up(&psthread_futex); 144 async_create_manager(); 145 futex_down(&psthread_futex); 146 } 147 148 pt = __tcb_get()->pst_data; 149 if (!context_save(&pt->ctx)) 150 return 1; // futex_up already done here 151 152 if (ctype == PS_PREEMPT) 153 list_append(&pt->link, &ready_list); 154 else if (ctype == PS_FROM_MANAGER) 155 list_append(&pt->link, &manager_list); 131 if (ctype == PS_TO_MANAGER || ctype == PS_FROM_DEAD) { 132 while (list_empty(&manager_list)) { 133 futex_up(&psthread_futex); 134 async_create_manager(); 135 futex_down(&psthread_futex); 136 } 137 } 156 138 157 if (ctype == PS_TO_MANAGER) 158 pt = list_get_instance(manager_list.next,psthread_data_t, link); 159 else 160 pt = list_get_instance(ready_list.next, psthread_data_t, link); 161 list_remove(&pt->link); 162 163 futex_up(&psthread_futex); 164 context_restore(&pt->ctx); 139 if (ctype != PS_FROM_DEAD) { 140 /* Save current state */ 141 srcpt = __tcb_get()->pst_data; 142 if (!context_save(&srcpt->ctx)) { 143 if (serialization_count) 144 srcpt->flags &= ~PSTHREAD_SERIALIZED; 145 return 1; // futex_up already done here 146 } 147 148 /* Save myself to correct run list */ 149 if (ctype == PS_PREEMPT) 150 list_append(&srcpt->link, &ready_list); 151 else if (ctype == PS_FROM_MANAGER) { 152 list_append(&srcpt->link, &manager_list); 153 threads_in_manager--; 154 } /* If ctype == PS_TO_MANAGER, don't save ourselves to any list, we should 155 * already be somewhere, or we will be lost */ 156 } 157 158 /* Choose new thread to run */ 159 if (ctype == PS_TO_MANAGER || ctype == PS_FROM_DEAD) { 160 dstpt = list_get_instance(manager_list.next,psthread_data_t, link); 161 if (serialization_count && ctype == PS_TO_MANAGER) { 162 serialized_threads++; 163 srcpt->flags |= PSTHREAD_SERIALIZED; 164 } 165 threads_in_manager++; 166 } else { 167 if (!list_empty(&serialized_list)) { 168 dstpt = list_get_instance(serialized_list.next, psthread_data_t, link); 169 serialized_threads--; 170 } else 171 dstpt = list_get_instance(ready_list.next, psthread_data_t, link); 172 } 173 list_remove(&dstpt->link); 174 175 futex_up(&psthread_futex); 176 context_restore(&dstpt->ctx); 165 177 166 178 ret_0: … … 183 195 pt = (psthread_data_t *) psthrid; 184 196 185 if (!pt->finished) { 186 mypt = __tcb_get()->pst_data; 187 if (context_save(&((psthread_data_t *) mypt)->ctx)) { 188 pt->waiter = (psthread_data_t *) mypt; 189 psthread_exit(); 190 } 191 } 197 /* TODO */ 198 printf("join unsupported\n"); 199 _exit(1); 200 192 201 retval = pt->retval; 193 202 … … 224 233 pt->finished = 0; 225 234 pt->waiter = NULL; 235 pt->flags = 0; 226 236 227 237 context_save(&pt->ctx); … … 239 249 pt = (psthread_data_t *) psthrid; 240 250 futex_down(&psthread_futex); 241 list_append(&pt->link, &ready_list); 251 if ((pt->flags & PSTHREAD_SERIALIZED)) 252 list_append(&pt->link, &serialized_list); 253 else 254 list_append(&pt->link, &ready_list); 242 255 futex_up(&psthread_futex); 243 256 } … … 272 285 return (pstid_t)__tcb_get()->pst_data; 273 286 } 287 288 /** Disable preemption 289 * 290 * If the thread wants to send several message in row and does not want 291 * to be preempted, it should start async_serialize_start() in the beginning 292 * of communication and async_serialize_end() in the end. If it is a 293 * true multithreaded application, it should protect the communication channel 294 * by a futex as well. Interrupt messages will can still be preempted. 295 */ 296 void psthread_inc_sercount(void) 297 { 298 serialization_count++; 299 } 300 301 void psthread_dec_sercount(void) 302 { 303 serialization_count--; 304 } -
libc/include/async.h
rd7eafd8 r085bd54 38 38 typedef void (*async_client_conn_t)(ipc_callid_t callid, ipc_call_t *call); 39 39 40 int async_manager(void); 40 static inline void async_manager(void) 41 { 42 psthread_schedule_next_adv(PS_TO_MANAGER); 43 } 44 41 45 ipc_callid_t async_get_call_timeout(ipc_call_t *call, suseconds_t usecs); 42 46 static inline ipc_callid_t async_get_call(ipc_call_t *data) … … 58 62 * @return Return code of message 59 63 */ 60 static inline ipcarg_t sync_send_2(int phoneid, ipcarg_t method, ipcarg_t arg1, ipcarg_t arg2, ipcarg_t *r1, ipcarg_t *r2)64 static inline ipcarg_t async_req_2(int phoneid, ipcarg_t method, ipcarg_t arg1, ipcarg_t arg2, ipcarg_t *r1, ipcarg_t *r2) 61 65 { 62 66 ipc_call_t result; … … 71 75 return rc; 72 76 } 73 #define sync_send(phoneid, method, arg1, r1) sync_send_2(phoneid, method, arg1, 0, r1, 0)77 #define async_req(phoneid, method, arg1, r1) async_req_2(phoneid, method, arg1, 0, r1, 0) 74 78 75 static inline ipcarg_t sync_send_3(int phoneid, ipcarg_t method, ipcarg_t arg1,79 static inline ipcarg_t async_req_3(int phoneid, ipcarg_t method, ipcarg_t arg1, 76 80 ipcarg_t arg2, ipcarg_t arg3, ipcarg_t *r1, 77 81 ipcarg_t *r2, ipcarg_t *r3) … … 103 107 104 108 109 /* Primitve functions for IPC communication */ 110 void async_msg_3(int phoneid, ipcarg_t method, ipcarg_t arg1, ipcarg_t arg2, 111 ipcarg_t arg3); 112 void async_msg_2(int phoneid, ipcarg_t method, ipcarg_t arg1, ipcarg_t arg2); 113 #define async_msg(ph,m,a1) async_msg_2(ph,m,a1,0) 114 115 static inline void async_serialize_start(void) 116 { 117 psthread_inc_sercount(); 118 } 119 static inline void async_serialize_end(void) 120 { 121 psthread_dec_sercount(); 122 } 123 105 124 extern atomic_t async_futex; 106 107 125 #endif -
libc/include/ipc/ipc.h
rd7eafd8 r085bd54 82 82 extern int ipc_forward_fast(ipc_callid_t callid, int phoneid, int method, ipcarg_t arg1); 83 83 84 85 /* Primitve functions for IPC communication */86 void send_call_3(int phoneid, ipcarg_t method, ipcarg_t arg1, ipcarg_t arg2,87 ipcarg_t arg3);88 void send_call_2(int phoneid, ipcarg_t method, ipcarg_t arg1, ipcarg_t arg2);89 #define send_call(ph,m,a1) send_call_2(ph,m,a1,0)90 /* These functions never preempt */91 void nsend_call_3(int phoneid, ipcarg_t method, ipcarg_t arg1,92 ipcarg_t arg2, ipcarg_t arg3);93 void nsend_call_2(int phoneid, ipcarg_t method, ipcarg_t arg1, ipcarg_t arg2);94 #define nsend_call(ph,m,a1) nsend_call_2(ph,m,a1,0)95 96 84 #endif -
libc/include/psthread.h
rd7eafd8 r085bd54 41 41 #endif /* context_set */ 42 42 43 #define PSTHREAD_SERIALIZED 1 44 43 45 typedef enum { 44 46 PS_TO_MANAGER, 45 47 PS_FROM_MANAGER, 46 PS_PREEMPT 48 PS_PREEMPT, 49 PS_FROM_DEAD 47 50 } pschange_type; 48 51 … … 76 79 void psthread_remove_manager(void); 77 80 pstid_t psthread_get_id(void); 81 void psthread_inc_sercount(void); 82 void psthread_dec_sercount(void); 78 83 79 84 static inline int psthread_schedule_next() {
Note:
See TracChangeset
for help on using the changeset viewer.
