Changeset 25451
- Timestamp:
- 05/11/08 11:25:35 (5 days ago)
- Files:
-
- haiku/trunk/headers/private/kernel/arch/x86/arch_kernel.h (modified) (1 diff)
- haiku/trunk/headers/private/kernel/team.h (modified) (1 diff)
- haiku/trunk/headers/private/kernel/thread_types.h (modified) (4 diffs)
- haiku/trunk/headers/private/kernel/tls.h (modified) (1 diff)
- haiku/trunk/headers/private/libroot/user_thread.h (added)
- haiku/trunk/src/system/kernel/arch/x86/arch_thread.cpp (modified) (2 diffs)
- haiku/trunk/src/system/kernel/Jamfile (modified) (1 diff)
- haiku/trunk/src/system/kernel/signal.cpp (modified) (3 diffs)
- haiku/trunk/src/system/kernel/team.cpp (modified) (16 diffs)
- haiku/trunk/src/system/kernel/thread.cpp (modified) (4 diffs)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
haiku/trunk/headers/private/kernel/arch/x86/arch_kernel.h
r25358 r25451 33 33 #define USER_TOP (USER_BASE + USER_SIZE) 34 34 35 #define USER_STACK_REGION 0x70000000 36 #define USER_STACK_REGION_SIZE (USER_TOP - USER_STACK_REGION) 35 #define KERNEL_USER_DATA_BASE 0x6fff0000 36 #define USER_STACK_REGION 0x70000000 37 #define USER_STACK_REGION_SIZE (USER_TOP - USER_STACK_REGION) 37 38 38 39 #endif /* _KERNEL_ARCH_x86_KERNEL_H */ haiku/trunk/headers/private/kernel/team.h
r24335 r25451 48 48 void *data); 49 49 50 struct user_thread* team_allocate_user_thread(struct team* team); 51 void team_free_user_thread(struct thread* thread); 52 50 53 // used in syscalls.c 51 54 thread_id _user_load_image(int32 argCount, const char **args, int32 envCount, haiku/trunk/headers/private/kernel/thread_types.h
r25326 r25451 72 72 struct realtime_sem_context; // defined in realtime_sem.cpp 73 73 struct select_info; 74 struct user_thread; // defined in libroot/user_thread.h 74 75 75 76 struct death_entry { … … 165 166 #endif // __cplusplus 166 167 168 169 struct free_user_thread { 170 struct free_user_thread* next; 171 struct user_thread* thread; 172 }; 167 173 168 174 struct team { … … 200 206 struct arch_team arch_info; 201 207 208 addr_t user_data; 209 area_id user_data_area; 210 size_t user_data_size; 211 size_t used_user_data; 212 struct free_user_thread* free_user_threads; 213 202 214 struct team_debug_info debug_info; 203 215 … … 240 252 bool signal_stack_enabled; 241 253 254 bool in_kernel; 255 bool was_yielded; 256 257 struct user_thread* user_thread; 258 242 259 struct { 243 260 uint8 parameters[32]; 244 261 } syscall_restart; 245 246 bool in_kernel;247 bool was_yielded;248 262 249 263 struct { haiku/trunk/headers/private/kernel/tls.h
r3073 r25451 18 18 TLS_ERRNO_SLOT, 19 19 TLS_ON_EXIT_THREAD_SLOT, 20 TLS_USER_THREAD_SLOT, 20 21 21 22 // Note: these entries can safely be changed between haiku/trunk/src/system/kernel/arch/x86/arch_thread.cpp
r24487 r25451 310 310 arch_thread_init_tls(struct thread *thread) 311 311 { 312 uint32 tls[TLS_ THREAD_ID_SLOT + 1];312 uint32 tls[TLS_USER_THREAD_SLOT + 1]; 313 313 int32 i; 314 314 … … 317 317 318 318 // initialize default TLS fields 319 memset(tls, 0, sizeof(tls)); 319 320 tls[TLS_BASE_ADDRESS_SLOT] = thread->user_local_storage; 320 321 tls[TLS_THREAD_ID_SLOT] = thread->id; 322 tls[TLS_USER_THREAD_SLOT] = (addr_t)thread->user_thread; 321 323 322 324 return user_memcpy((void *)thread->user_local_storage, tls, sizeof(tls)); haiku/trunk/src/system/kernel/Jamfile
r25375 r25451 11 11 } 12 12 13 UsePrivateHeaders libroot ; 13 14 UsePrivateHeaders shared ; 14 15 UsePrivateHeaders runtime_loader ; haiku/trunk/src/system/kernel/signal.cpp
r25228 r25451 25 25 #include <tracing.h> 26 26 #include <user_debugger.h> 27 #include <user_thread.h> 27 28 #include <util/AutoLock.h> 28 29 … … 43 44 (SIGNAL_TO_MASK(SIGCHLD) | SIGNAL_TO_MASK(SIGWINCH) \ 44 45 | SIGNAL_TO_MASK(SIGCONT)) 46 #define NON_DEFERRABLE_SIGNALS \ 47 (KILL_SIGNALS \ 48 | SIGNAL_TO_MASK(SIGILL) \ 49 | SIGNAL_TO_MASK(SIGFPE) \ 50 | SIGNAL_TO_MASK(SIGSEGV)) 45 51 46 52 … … 270 276 if (signalMask == 0) 271 277 return 0; 278 279 if (thread->user_thread->defer_signals > 0 280 && (signalMask & NON_DEFERRABLE_SIGNALS) == 0) { 281 thread->user_thread->pending_signals = signalMask; 282 return 0; 283 } 284 285 thread->user_thread->pending_signals = 0; 272 286 273 287 bool restart = (atomic_and(&thread->flags, haiku/trunk/src/system/kernel/team.cpp
r25336 r25451 1 1 /* 2 * Copyright 2008, Ingo Weinhold, ingo_weinhold@gmx.de. 2 3 * Copyright 2002-2008, Axel Dörfler, axeld@pinc-software.de. 3 4 * Distributed under the terms of the MIT License. … … 36 37 #include <tracing.h> 37 38 #include <user_runtime.h> 39 #include <user_thread.h> 38 40 #include <usergroup.h> 39 41 #include <vfs.h> … … 70 72 addr_t user_local_storage; 71 73 sigset_t sig_block_mask; 74 struct user_thread* user_thread; 72 75 73 76 struct arch_fork_arg arch_info; … … 831 834 team->flags = 0; 832 835 team->death_sem = -1; 836 team->user_data_area = -1; 837 team->user_data = 0; 838 team->used_user_data = 0; 839 team->user_data_size = 0; 840 team->free_user_threads = NULL; 833 841 834 842 team->supplementary_groups = NULL; … … 912 920 delete entry; 913 921 922 while (free_user_thread* entry = team->free_user_threads) { 923 team->free_user_threads = entry->next; 924 free(entry); 925 } 926 914 927 malloc_referenced_release(team->supplementary_groups); 915 928 … … 933 946 934 947 return size + (argc + 1) * sizeof(char *) + sizeof(struct user_space_program_args); 948 } 949 950 951 static status_t 952 create_team_user_data(struct team* team) 953 { 954 void* address = (void*)KERNEL_USER_DATA_BASE; 955 size_t size = 4 * B_PAGE_SIZE; 956 team->user_data_area = create_area_etc(team, "user area", &address, 957 B_BASE_ADDRESS, size, B_FULL_LOCK, B_READ_AREA | B_WRITE_AREA); 958 if (team->user_data_area < 0) 959 return team->user_data_area; 960 961 team->user_data = (addr_t)address; 962 team->used_user_data = 0; 963 team->user_data_size = size; 964 team->free_user_threads = NULL; 965 966 return B_OK; 967 } 968 969 970 static void 971 delete_team_user_data(struct team* team) 972 { 973 if (team->user_data_area >= 0) { 974 delete_area_etc(team, team->user_data_area); 975 team->user_data = 0; 976 team->used_user_data = 0; 977 team->user_data_size = 0; 978 team->user_data_area = -1; 979 while (free_user_thread* entry = team->free_user_threads) { 980 team->free_user_threads = entry->next; 981 free(entry); 982 } 983 } 935 984 } 936 985 … … 1005 1054 TRACE(("team_create_thread_start: entry thread %ld\n", t->id)); 1006 1055 1056 // get a user thread for the main thread 1057 t->user_thread = team_allocate_user_thread(team); 1058 1007 1059 // create an initial primary stack area 1008 1060 … … 1217 1269 threadName = args[0]; 1218 1270 1271 // create the user data area 1272 status = create_team_user_data(team); 1273 if (status != B_OK) 1274 goto err4; 1275 1219 1276 // Create a kernel thread, but under the context of the new team 1220 1277 // The new thread will take over ownership of teamArgs … … 1223 1280 if (thread < 0) { 1224 1281 status = thread; 1225 goto err 4;1282 goto err5; 1226 1283 } 1227 1284 … … 1265 1322 return thread; 1266 1323 1324 err5: 1325 delete_team_user_data(team); 1267 1326 err4: 1268 1327 vm_put_address_space(team->address_space); … … 1363 1422 user_debug_prepare_for_exec(); 1364 1423 1424 delete_team_user_data(team); 1365 1425 vm_delete_areas(team->address_space); 1366 1426 delete_owned_ports(team->id); … … 1371 1431 team->realtime_sem_context = NULL; 1372 1432 1433 status = create_team_user_data(team); 1434 if (status != B_OK) { 1435 // creating the user data failed -- we're toast 1436 // TODO: We should better keep the old user area in the first place. 1437 exit_thread(status); 1438 return status; 1439 } 1440 1373 1441 user_debug_finish_after_exec(); 1374 1442 … … 1423 1491 thread->user_local_storage = forkArgs->user_local_storage; 1424 1492 thread->sig_block_mask = forkArgs->sig_block_mask; 1493 thread->user_thread = forkArgs->user_thread; 1425 1494 1426 1495 arch_thread_init_tls(thread); … … 1510 1579 // ToDo: all stacks of other threads than the current one could be left out 1511 1580 1581 forkArgs->user_thread = NULL; 1582 1512 1583 cookie = 0; 1513 1584 while (get_next_area_info(B_CURRENT_TEAM, &cookie, &info) == B_OK) { … … 1520 1591 } 1521 1592 1522 if (info.area == parentThread->user_stack_area) 1593 if (info.area == parentThread->user_stack_area) { 1523 1594 forkArgs->user_stack_area = area; 1595 } else if (info.area == parentTeam->user_data_area) { 1596 team->user_data = (addr_t)address; 1597 team->used_user_data = 0; 1598 team->user_data_size = info.size; 1599 team->user_data_area = area; 1600 team->free_user_threads = NULL; 1601 forkArgs->user_thread = team_allocate_user_thread(team); 1602 } 1524 1603 } 1525 1604 1526 1605 if (status < B_OK) 1527 1606 goto err4; 1607 1608 if (forkArgs->user_thread == NULL) { 1609 #if KDEBUG 1610 panic("user data area not found, parent area is %ld", 1611 parentTeam->user_data_area); 1612 #endif 1613 status = B_ERROR; 1614 goto err4; 1615 } 1528 1616 1529 1617 forkArgs->user_stack_base = parentThread->user_stack_base; … … 2556 2644 free(watcher); 2557 2645 return B_OK; 2646 } 2647 2648 2649 /*! The team lock must be held or the team must still be single threaded. 2650 */ 2651 struct user_thread* 2652 team_allocate_user_thread(struct team* team) 2653 { 2654 if (team->user_data == 0) 2655 return NULL; 2656 2657 user_thread* thread = NULL; 2658 2659 // take an entry from the free list, if any 2660 if (struct free_user_thread* entry = team->free_user_threads) { 2661 thread = entry->thread; 2662 team->free_user_threads = entry->next; 2663 deferred_free(entry); 2664 return thread; 2665 } else { 2666 // enough space left? 2667 size_t needed = _ALIGN(sizeof(user_thread)); 2668 if (team->user_data_size - team->used_user_data < needed) 2669 return NULL; 2670 // TODO: This imposes a per team thread limit! We should resize the 2671 // area, if necessary. That's problematic at this point, though, since 2672 // we've got the team lock. 2673 2674 thread = (user_thread*)(team->user_data + team->used_user_data); 2675 team->used_user_data += needed; 2676 } 2677 2678 thread->defer_signals = 0; 2679 thread->pending_signals = 0; 2680 thread->wait_status = B_OK; 2681 2682 return thread; 2683 } 2684 2685 2686 /*! The team lock must not be held. \a thread must be the current thread. 2687 */ 2688 void 2689 team_free_user_thread(struct thread* thread) 2690 { 2691 user_thread* userThread = thread->user_thread; 2692 if (userThread == NULL) 2693 return; 2694 2695 // create a free list entry 2696 free_user_thread* entry 2697 = (free_user_thread*)malloc(sizeof(free_user_thread)); 2698 if (entry == NULL) { 2699 // we have to leak the user thread :-/ 2700 return; 2701 } 2702 2703 InterruptsSpinLocker _(team_spinlock); 2704 2705 entry->thread = userThread; 2706 entry->next = thread->team->free_user_threads; 2707 thread->team->free_user_threads = entry; 2558 2708 } 2559 2709 haiku/trunk/src/system/kernel/thread.cpp
r25434 r25451 445 445 // look at the team, make sure it's not being deleted 446 446 team = team_get_team_struct_locked(attributes.team); 447 if (team != NULL && team->state != TEAM_STATE_DEATH) { 447 448 if (team == NULL || team->state == TEAM_STATE_DEATH) 449 abort = true; 450 451 if (!abort && !kernel) { 452 thread->user_thread = team_allocate_user_thread(team); 453 abort = thread->user_thread == NULL; 454 } 455 456 if (!abort) { 448 457 // Debug the new thread, if the parent thread required that (see above), 449 458 // or the respective global team debug flag is set. But only, if a … … 458 467 459 468 insert_thread_into_team(team, thread); 460 } else 461 abort = true; 469 } 462 470 463 471 RELEASE_TEAM_LOCK(); … … 1408 1416 // this was the main thread in this team, so we will delete that as well 1409 1417 deleteTeam = true; 1410 } else 1418 } else { 1411 1419 threadDeathEntry = (death_entry*)malloc(sizeof(death_entry)); 1420 team_free_user_thread(thread); 1421 } 1412 1422 1413 1423 // remove this thread from the current team and add it to the kernel … … 2938 2948 return common_setrlimit(resource, &resourceLimit); 2939 2949 } 2940
