Changeset 085bd54 in mainline for libc/generic/psthread.c
- 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
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
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 }
Note:
See TracChangeset
for help on using the changeset viewer.