diff --git a/headers/private/kernel/user_mutex.h b/headers/private/kernel/user_mutex.h index 4a21c7a3ba..adc4477806 100644 --- a/headers/private/kernel/user_mutex.h +++ b/headers/private/kernel/user_mutex.h @@ -7,6 +7,7 @@ #include +#include #ifdef __cplusplus @@ -17,6 +18,7 @@ struct user_mutex_context; void user_mutex_init(); void delete_user_mutex_context(struct user_mutex_context* context); +status_t allocate_team_user_mutex_context(Team* team); status_t _user_mutex_lock(int32* mutex, const char* name, uint32 flags, bigtime_t timeout); diff --git a/src/system/kernel/locks/user_mutex.cpp b/src/system/kernel/locks/user_mutex.cpp index 1b07542ed8..759b4dd7a0 100644 --- a/src/system/kernel/locks/user_mutex.cpp +++ b/src/system/kernel/locks/user_mutex.cpp @@ -219,31 +219,25 @@ user_mutex_init() } -struct user_mutex_context* -get_team_user_mutex_context() +status_t +allocate_team_user_mutex_context(Team* team) { - struct user_mutex_context* context = - thread_get_current_thread()->team->user_mutex_context; - if (context != NULL) - return context; + team->AssertLocked(); + ASSERT(team->user_mutex_context == NULL); - Team* team = thread_get_current_thread()->team; - TeamLocker teamLocker(team); - if (team->user_mutex_context != NULL) - return team->user_mutex_context; - - context = new(std::nothrow) user_mutex_context; + struct user_mutex_context* context = new(std::nothrow) user_mutex_context; if (context == NULL) - return NULL; + return B_NO_MEMORY; context->lock = RW_LOCK_INITIALIZER("user mutex table"); - if (context->table.Init() != B_OK) { + status_t status = context->table.Init(); + if (status != B_OK) { delete context; - return NULL; + return status; } team->user_mutex_context = context; - return context; + return B_OK; } @@ -469,10 +463,10 @@ struct UserMutexContextFetcher { fAddress(0) { if (!fShared) { - fContext = get_team_user_mutex_context(); + fContext = thread_get_current_thread()->team->user_mutex_context; if (fContext == NULL) { - panic("UserMutexContext allocation failed!"); - fInitStatus = B_NO_MEMORY; + _user_debugger("single-threaded team attempted mutex operation"); + fInitStatus = EDEADLK; return; } diff --git a/src/system/kernel/thread.cpp b/src/system/kernel/thread.cpp index dcbdf114a4..fd389a9d20 100644 --- a/src/system/kernel/thread.cpp +++ b/src/system/kernel/thread.cpp @@ -46,6 +46,7 @@ #include #include #include +#include #include #include #include @@ -1084,6 +1085,13 @@ thread_create_thread(const ThreadCreationAttributes& attributes, bool kernel) bool debugNewThread = false; if (!kernel) { + // ensure there's a user_mutex_context, if this isn't the main thread + if (team->main_thread != NULL && team->user_mutex_context == NULL) { + status_t status = allocate_team_user_mutex_context(team); + if (status != B_OK) + return status; + } + // allocate the user_thread structure, if not already allocated if (thread->user_thread == NULL) { thread->user_thread = team_allocate_user_thread(team);