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 <SupportDefs.h>
|
||||||
|
#include <thread_types.h>
|
||||||
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
@@ -17,6 +18,7 @@ struct user_mutex_context;
|
|||||||
|
|
||||||
void user_mutex_init();
|
void user_mutex_init();
|
||||||
void delete_user_mutex_context(struct user_mutex_context* context);
|
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,
|
status_t _user_mutex_lock(int32* mutex, const char* name, uint32 flags,
|
||||||
bigtime_t timeout);
|
bigtime_t timeout);
|
||||||
|
|||||||
@@ -219,31 +219,25 @@ user_mutex_init()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
struct user_mutex_context*
|
status_t
|
||||||
get_team_user_mutex_context()
|
allocate_team_user_mutex_context(Team* team)
|
||||||
{
|
{
|
||||||
struct user_mutex_context* context =
|
team->AssertLocked();
|
||||||
thread_get_current_thread()->team->user_mutex_context;
|
ASSERT(team->user_mutex_context == NULL);
|
||||||
if (context != NULL)
|
|
||||||
return context;
|
|
||||||
|
|
||||||
Team* team = thread_get_current_thread()->team;
|
struct user_mutex_context* context = new(std::nothrow) user_mutex_context;
|
||||||
TeamLocker teamLocker(team);
|
|
||||||
if (team->user_mutex_context != NULL)
|
|
||||||
return team->user_mutex_context;
|
|
||||||
|
|
||||||
context = new(std::nothrow) user_mutex_context;
|
|
||||||
if (context == NULL)
|
if (context == NULL)
|
||||||
return NULL;
|
return B_NO_MEMORY;
|
||||||
|
|
||||||
context->lock = RW_LOCK_INITIALIZER("user mutex table");
|
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;
|
delete context;
|
||||||
return NULL;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
team->user_mutex_context = context;
|
team->user_mutex_context = context;
|
||||||
return context;
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -469,10 +463,10 @@ struct UserMutexContextFetcher {
|
|||||||
fAddress(0)
|
fAddress(0)
|
||||||
{
|
{
|
||||||
if (!fShared) {
|
if (!fShared) {
|
||||||
fContext = get_team_user_mutex_context();
|
fContext = thread_get_current_thread()->team->user_mutex_context;
|
||||||
if (fContext == NULL) {
|
if (fContext == NULL) {
|
||||||
panic("UserMutexContext allocation failed!");
|
_user_debugger("single-threaded team attempted mutex operation");
|
||||||
fInitStatus = B_NO_MEMORY;
|
fInitStatus = EDEADLK;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -46,6 +46,7 @@
|
|||||||
#include <tls.h>
|
#include <tls.h>
|
||||||
#include <user_runtime.h>
|
#include <user_runtime.h>
|
||||||
#include <user_thread.h>
|
#include <user_thread.h>
|
||||||
|
#include <user_mutex.h>
|
||||||
#include <vfs.h>
|
#include <vfs.h>
|
||||||
#include <vm/vm.h>
|
#include <vm/vm.h>
|
||||||
#include <vm/VMAddressSpace.h>
|
#include <vm/VMAddressSpace.h>
|
||||||
@@ -1084,6 +1085,13 @@ thread_create_thread(const ThreadCreationAttributes& attributes, bool kernel)
|
|||||||
|
|
||||||
bool debugNewThread = false;
|
bool debugNewThread = false;
|
||||||
if (!kernel) {
|
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
|
// allocate the user_thread structure, if not already allocated
|
||||||
if (thread->user_thread == NULL) {
|
if (thread->user_thread == NULL) {
|
||||||
thread->user_thread = team_allocate_user_thread(team);
|
thread->user_thread = team_allocate_user_thread(team);
|
||||||
|
|||||||
Reference in New Issue
Block a user