Changeset ef4218f in mainline
- Timestamp:
- 2018-11-09T17:54:05Z (6 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- 1a5fe4f
- Parents:
- d19b3fc
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
kernel/generic/src/synch/futex.c
rd19b3fc ref4218f 45 45 * encountered before). Futex object's lifetime is governed by 46 46 * a reference count that represents the number of all the different 47 * user space virtual addresses from all tasks that map to the 48 * physical address of the futex variable. A futex object is freed 47 * tasks that reference the futex variable. A futex object is freed 49 48 * when the last task having accessed the futex exits. 50 49 * … … 75 74 /** Task specific pointer to a global kernel futex object. */ 76 75 typedef struct futex_ptr { 77 /** Li st of all futex pointers used by thetask. */78 link_t all_link;76 /** Link for the list of all futex pointers used by a task. */ 77 link_t task_link; 79 78 /** Kernel futex object. */ 80 79 futex_t *futex; 81 /** User space virtual address of the futex variable in the task. */82 uintptr_t uaddr;83 80 } futex_ptr_t; 84 81 … … 136 133 137 134 list_foreach_safe(TASK->futex_list, cur_link, next_link) { 138 futex_ptr_t *fut_ptr = member_to_inst(cur_link, futex_ptr_t, all_link); 139 140 /* 141 * The function is free to free the futex. Moreover 142 * release_ref() only frees the futex if this is the last task 143 * referencing the futex. Therefore, only threads of this task 144 * may have referenced the futex if it is to be freed. 145 */ 146 futex_release_ref_locked(fut_ptr->futex); 135 futex_ptr_t *futex_ptr = member_to_inst(cur_link, futex_ptr_t, 136 task_link); 137 138 futex_release_ref_locked(futex_ptr->futex); 139 free(futex_ptr); 147 140 } 148 141 … … 166 159 { 167 160 assert(spinlock_locked(&futex_ht_lock)); 168 assert( 0 < futex->refcount);161 assert(futex->refcount > 0); 169 162 ++futex->refcount; 170 163 } … … 174 167 { 175 168 assert(spinlock_locked(&futex_ht_lock)); 176 assert( 0 < futex->refcount);169 assert(futex->refcount > 0); 177 170 178 171 --futex->refcount; 179 172 180 if ( 0 == futex->refcount) {173 if (futex->refcount == 0) 181 174 hash_table_remove(&futex_ht, &futex->paddr); 182 }183 175 } 184 176 … … 202 194 if (!futex) 203 195 return NULL; 196 197 futex_ptr_t *futex_ptr = malloc(sizeof(futex_ptr_t)); 198 if (!futex_ptr) { 199 free(futex); 200 return NULL; 201 } 204 202 205 203 /* … … 207 205 * if it is not present). 208 206 */ 207 spinlock_lock(&TASK->futex_list_lock); 209 208 spinlock_lock(&futex_ht_lock); 210 209 … … 214 213 free(futex); 215 214 futex = member_to_inst(fut_link, futex_t, ht_link); 216 futex_add_ref(futex); 215 216 /* 217 * See if the futex is already known to the TASK 218 */ 219 bool found = false; 220 list_foreach(TASK->futex_list, task_link, futex_ptr_t, fp) { 221 if (fp->futex->paddr == paddr) { 222 found = true; 223 break; 224 } 225 } 226 /* 227 * If not, put it on the TASK->futex_list and bump its reference 228 * count 229 */ 230 if (!found) { 231 list_append(&futex_ptr->task_link, &TASK->futex_list); 232 futex_add_ref(futex); 233 } else 234 free(futex_ptr); 217 235 } else { 218 236 futex_initialize(futex, paddr); 219 237 hash_table_insert(&futex_ht, &futex->ht_link); 238 239 /* 240 * This is a new futex, so it is not on the TASK->futex_list yet 241 */ 242 futex_ptr->futex = futex; 243 list_append(&futex_ptr->task_link, &TASK->futex_list); 220 244 } 221 245 222 246 spinlock_unlock(&futex_ht_lock); 247 spinlock_unlock(&TASK->futex_list_lock); 223 248 224 249 return futex; … … 250 275 251 276 /** Sleep in futex wait queue with a timeout. 277 * 252 278 * If the sleep times out or is interrupted, the next wakeup is ignored. 253 279 * The userspace portion of the call must handle this condition.
Note:
See TracChangeset
for help on using the changeset viewer.