kernel: Allocate user_mutex_contexts when adding the second thread to a team.
This allows us to gracefully fail if memory allocation fails, rather than panic()ing. If a single-threaded application tries to wait on a non-shared user_mutex in single-threaded mode, it will now be dropped into the debugger.
This commit is contained in:
@@ -7,6 +7,7 @@
|
||||
|
||||
|
||||
#include <SupportDefs.h>
|
||||
#include <thread_types.h>
|
||||
|
||||
|
||||
#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);
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -46,6 +46,7 @@
|
||||
#include <tls.h>
|
||||
#include <user_runtime.h>
|
||||
#include <user_thread.h>
|
||||
#include <user_mutex.h>
|
||||
#include <vfs.h>
|
||||
#include <vm/vm.h>
|
||||
#include <vm/VMAddressSpace.h>
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user