Author: bonefish Date: 2011-05-04 00:07:03 +0200 (Wed, 04 May 2011) New Revision: 41310 Changeset: https://dev.haiku-os.org/changeset/41310 Modified: haiku/branches/developer/bonefish/signals/headers/private/kernel/team.h haiku/branches/developer/bonefish/signals/headers/private/kernel/thread_types.h haiku/branches/developer/bonefish/signals/src/system/kernel/signal.cpp haiku/branches/developer/bonefish/signals/src/system/kernel/team.cpp Log: * Renamed process_group and process_session to ProcessGroup and ProcessSession respectively and C++-ified the structs a bit. Also added locking, though it is not used yet. * Changed sGroupHash from hash_table to BOpenHashTable. Modified: haiku/branches/developer/bonefish/signals/headers/private/kernel/team.h =================================================================== --- haiku/branches/developer/bonefish/signals/headers/private/kernel/team.h 2011-05-03 22:01:09 UTC (rev 41309) +++ haiku/branches/developer/bonefish/signals/headers/private/kernel/team.h 2011-05-03 22:07:03 UTC (rev 41310) @@ -25,9 +25,8 @@ void team_remove_team(Team *team); port_id team_shutdown_team(Team *team, cpu_status& state); void team_delete_team(Team *team, port_id debuggerPort); -struct process_group *team_get_process_group_locked( - struct process_session *session, pid_t id); -void team_delete_process_group(struct process_group *group); +struct ProcessGroup *team_get_process_group_locked(ProcessSession* session, + pid_t id); Team *team_get_kernel_team(void); team_id team_get_kernel_team_id(void); team_id team_get_current_team_id(void); Modified: haiku/branches/developer/bonefish/signals/headers/private/kernel/thread_types.h =================================================================== --- haiku/branches/developer/bonefish/signals/headers/private/kernel/thread_types.h 2011-05-03 22:01:09 UTC (rev 41309) +++ haiku/branches/developer/bonefish/signals/headers/private/kernel/thread_types.h 2011-05-03 22:07:03 UTC (rev 41310) @@ -14,6 +14,7 @@ #include <arch/thread_types.h> #include <condition_variable.h> +#include <heap.h> #include <lock.h> #include <signal.h> #include <smp.h> @@ -83,23 +84,6 @@ uint16 signal; }; -struct process_session { - pid_t id; - int32 group_count; - int32 controlling_tty; // index of the controlling tty, - // -1 if none - pid_t foreground_group; -}; - -struct process_group { - struct process_group *next; // next in hash - struct process_session *session; - pid_t id; - int32 refs; - BKernel::Team *teams; - bool orphaned; -}; - struct team_loading_info { Thread* thread; // the waiting thread status_t result; // the result of the loading @@ -243,7 +227,7 @@ Team *group_next; pid_t group_id; pid_t session_id; - struct process_group *group; + struct ProcessGroup *group; int num_threads; // number of threads in this team int state; // current team state, see above int32 flags; @@ -427,12 +411,57 @@ struct arch_thread arch_info; }; + +struct ProcessSession { + pid_t id; + int32 group_count; + int32 controlling_tty; // index of the controlling tty, + // -1 if none + pid_t foreground_group; + +public: + ProcessSession(pid_t id); + ~ProcessSession(); + + bool Lock() + { mutex_lock(&fLock); return true; } + void Unlock() + { mutex_unlock(&fLock); } + +private: + mutex fLock; +}; + + +struct ProcessGroup : DeferredDeletable { + struct ProcessGroup *next; // next in hash + struct ProcessSession *session; + pid_t id; + int32 refs; + BKernel::Team *teams; + bool orphaned; + +public: + ProcessGroup(pid_t id); + ~ProcessGroup(); + + bool Lock() + { mutex_lock(&fLock); return true; } + void Unlock() + { mutex_unlock(&fLock); } + +private: + mutex fLock; +}; + } // namespace BKernel using BKernel::Team; using BKernel::TeamListEntry; using BKernel::TeamListIterator; using BKernel::Thread; +using BKernel::ProcessSession; +using BKernel::ProcessGroup; struct thread_queue { Modified: haiku/branches/developer/bonefish/signals/src/system/kernel/signal.cpp =================================================================== --- haiku/branches/developer/bonefish/signals/src/system/kernel/signal.cpp 2011-05-03 22:01:09 UTC (rev 41309) +++ haiku/branches/developer/bonefish/signals/src/system/kernel/signal.cpp 2011-05-03 22:07:03 UTC (rev 41310) @@ -633,7 +633,7 @@ // send a signal to the specified process group // (the absolute value of the id) - struct process_group *group; + ProcessGroup *group; // TODO: handle -1 correctly if (id == 0 || id == -1) { Modified: haiku/branches/developer/bonefish/signals/src/system/kernel/team.cpp =================================================================== --- haiku/branches/developer/bonefish/signals/src/system/kernel/team.cpp 2011-05-03 22:01:09 UTC (rev 41309) +++ haiku/branches/developer/bonefish/signals/src/system/kernel/team.cpp 2011-05-03 22:07:03 UTC (rev 41310) @@ -52,7 +52,6 @@ #include <vm/vm.h> #include <vm/VMAddressSpace.h> #include <util/AutoLock.h> -#include <util/khash.h> //#define TRACE_TEAM #ifdef TRACE_TEAM @@ -258,6 +257,37 @@ TeamList fList; }; + +// #pragma mark - ProcessGroupHashDefinition + + +struct ProcessGroupHashDefinition { + typedef pid_t KeyType; + typedef ProcessGroup ValueType; + + size_t HashKey(pid_t key) const + { + return key; + } + + size_t Hash(ProcessGroup* value) const + { + return HashKey(value->id); + } + + bool Compare(pid_t key, ProcessGroup* value) const + { + return value->id == key; + } + + ProcessGroup*& GetLink(ProcessGroup* value) const + { + return value->next; + } +}; + +typedef BOpenHashTable<ProcessGroupHashDefinition> ProcessGroupHashTable; + } // unnamed namespace @@ -265,7 +295,7 @@ static TeamTable sTeamHash; -static hash_table* sGroupHash = NULL; +static ProcessGroupHashTable sGroupHash; static Team* sKernelTeam = NULL; // some arbitrarily chosen limits -- should probably depend on the available @@ -704,6 +734,61 @@ } +// #pragma mark - ProcessGroup + + +ProcessGroup::ProcessGroup(pid_t id) + : + session(NULL), + id(id), + refs(0), + teams(NULL), + orphaned(true) +{ + char lockName[32]; + snprintf(lockName, sizeof(lockName), "Group:%" B_PRId32, id); + mutex_init_etc(&fLock, lockName, MUTEX_FLAG_CLONE_NAME); +} + + +ProcessGroup::~ProcessGroup() +{ + TRACE(("ProcessGroup::~ProcessGroup(): id = %ld\n", group->id)); + + // remove_group_from_session() keeps this pointer around + // only if the session can be freed as well + if (session != NULL) { + TRACE(("ProcessGroup::~ProcessGroup(): frees session %ld\n", + session->id)); + delete session; + } + + mutex_destroy(&fLock); +} + + +// #pragma mark - ProcessSession + + +ProcessSession::ProcessSession(pid_t id) + : + id(id), + group_count(0), + controlling_tty(-1), + foreground_group(-1) +{ + char lockName[32]; + snprintf(lockName, sizeof(lockName), "Session:%" B_PRId32, id); + mutex_init_etc(&fLock, lockName, MUTEX_FLAG_CLONE_NAME); +} + + +ProcessSession::~ProcessSession() +{ + mutex_destroy(&fLock); +} + + // #pragma mark - Private functions @@ -791,32 +876,6 @@ } -static int -process_group_compare(void* _group, const void* _key) -{ - struct process_group* group = (struct process_group*)_group; - const struct team_key* key = (const struct team_key*)_key; - - if (group->id == key->id) - return 0; - - return 1; -} - - -static uint32 -process_group_hash(void* _group, const void* _key, uint32 range) -{ - struct process_group* group = (struct process_group*)_group; - const struct team_key* key = (const struct team_key*)_key; - - if (group != NULL) - return group->id % range; - - return (uint32)key->id % range; -} - - static void insert_team_into_parent(Team* parent, Team* team) { @@ -890,38 +949,20 @@ } -static void -deferred_delete_process_group(struct process_group* group) -{ - if (group == NULL) - return; - - // remove_group_from_session() keeps this pointer around - // only if the session can be freed as well - if (group->session) { - TRACE(("deferred_delete_process_group(): frees session %ld\n", - group->session->id)); - deferred_free(group->session); - } - - deferred_free(group); -} - - /*! Removes a group from a session, and puts the session object back into the session cache, if it's not used anymore. You must hold the team lock when calling this function. */ static void -remove_group_from_session(struct process_group* group) +remove_group_from_session(ProcessGroup* group) { - struct process_session* session = group->session; + ProcessSession* session = group->session; // the group must be in any session to let this function have any effect if (session == NULL) return; - hash_remove(sGroupHash, group); + sGroupHash.RemoveUnchecked(group); // we cannot free the resource here, so we're keeping the group link // around - this way it'll be freed by free_process_group() @@ -935,7 +976,7 @@ static void acquire_process_group_ref(pid_t groupID) { - process_group* group = team_get_process_group_locked(NULL, groupID); + ProcessGroup* group = team_get_process_group_locked(NULL, groupID); if (group == NULL) { panic("acquire_process_group_ref(): unknown group ID: %ld", groupID); return; @@ -950,7 +991,7 @@ static void release_process_group_ref(pid_t groupID) { - process_group* group = team_get_process_group_locked(NULL, groupID); + ProcessGroup* group = team_get_process_group_locked(NULL, groupID); if (group == NULL) { panic("release_process_group_ref(): unknown group ID: %ld", groupID); return; @@ -967,27 +1008,26 @@ // group is no longer used remove_group_from_session(group); - deferred_delete_process_group(group); + deferred_delete(group); } /*! You must hold the team lock when calling this function. */ static void -insert_group_into_session(struct process_session* session, - struct process_group* group) +insert_group_into_session(ProcessSession* session, ProcessGroup* group) { if (group == NULL) return; group->session = session; - hash_insert(sGroupHash, group); + sGroupHash.InsertUnchecked(group); session->group_count++; } /*! You must hold the team lock when calling this function. */ static void -insert_team_into_group(struct process_group* group, Team* team) +insert_team_into_group(ProcessGroup* group, Team* team) { team->group = group; team->group_id = group->id; @@ -1006,7 +1046,7 @@ static void remove_team_from_group(Team* team) { - struct process_group* group = team->group; + ProcessGroup* group = team->group; Team* current; Team* last = NULL; @@ -1035,40 +1075,6 @@ } -static struct process_group* -create_process_group(pid_t id) -{ - struct process_group* group - = (struct process_group*)malloc(sizeof(struct process_group)); - if (group == NULL) - return NULL; - - group->id = id; - group->refs = 0; - group->session = NULL; - group->teams = NULL; - group->orphaned = true; - return group; -} - - -static struct process_session* -create_process_session(pid_t id) -{ - struct process_session* session - = (struct process_session*)malloc(sizeof(struct process_session)); - if (session == NULL) - return NULL; - - session->id = id; - session->group_count = 0; - session->controlling_tty = -1; - session->foreground_group = -1; - - return session; -} - - static status_t create_team_user_data(Team* team) { @@ -1913,7 +1919,7 @@ { Team* team; - struct process_group* group = team_get_process_group_locked( + ProcessGroup* group = team_get_process_group_locked( parent->group->session, groupID); if (group == NULL) return false; @@ -2209,11 +2215,11 @@ } -/*! Updates the \c orphaned field of a process_group and returns its new value. +/*! Updates the \c orphaned field of a ProcessGroup and returns its new value. Interrupts must be disabled and team lock be held. */ static bool -update_orphaned_process_group(process_group* group, pid_t dyingProcess) +update_orphaned_process_group(ProcessGroup* group, pid_t dyingProcess) { // Orphaned Process Group: "A process group in which the parent of every // member is either itself a member of the group or is not a member of the @@ -2245,7 +2251,7 @@ Interrupts must be disabled and team lock be held. */ static bool -process_group_has_stopped_processes(process_group* group) +process_group_has_stopped_processes(ProcessGroup* group) { SpinLocker _(gThreadSpinlock); @@ -2267,24 +2273,25 @@ status_t team_init(kernel_args* args) { - struct process_session* session; - struct process_group* group; + ProcessSession* session; + ProcessGroup* group; // create the team hash table new(&sTeamHash) TeamTable; if (sTeamHash.Init() != B_OK) panic("Failed to init team hash table!"); - sGroupHash = hash_init(16, offsetof(struct process_group, next), - &process_group_compare, &process_group_hash); + new(&sGroupHash) ProcessGroupHashTable; + if (sGroupHash.Init() != B_OK) + panic("Failed to init process group hash table!"); // create initial session and process groups - session = create_process_session(1); + session = new(std::nothrow) ProcessSession(1); if (session == NULL) panic("Could not create initial session.\n"); - group = create_process_group(1); + group = new(std::nothrow) ProcessGroup(1); if (group == NULL) panic("Could not create initial process group.\n"); @@ -2422,14 +2429,10 @@ /*! This searches the session of the team for the specified group ID. You must hold the team lock when you call this function. */ -struct process_group* -team_get_process_group_locked(struct process_session* session, pid_t id) +ProcessGroup* +team_get_process_group_locked(ProcessSession* session, pid_t id) { - struct process_group* group; - struct team_key key; - key.id = id; - - group = (struct process_group*)hash_lookup(sGroupHash, &key); + ProcessGroup* group = sGroupHash.Lookup(id); if (group != NULL && (session == NULL || session == group->session)) return group; @@ -2438,26 +2441,6 @@ void -team_delete_process_group(struct process_group* group) -{ - if (group == NULL) - return; - - TRACE(("team_delete_process_group(id = %ld)\n", group->id)); - - // remove_group_from_session() keeps this pointer around - // only if the session can be freed as well - if (group->session) { - TRACE(("team_delete_process_group(): frees session %ld\n", - group->session->id)); - free(group->session); - } - - free(group); -} - - -void team_set_controlling_tty(int32 ttyIndex) { Team* team = thread_get_current_thread()->team; @@ -2488,14 +2471,14 @@ InterruptsSpinLocker locker(gTeamSpinlock); - process_session* session = team->group->session; + ProcessSession* session = team->group->session; // must be the controlling tty of the calling process if (session->controlling_tty != ttyIndex) return ENOTTY; // check process group -- must belong to our session - process_group* group = team_get_process_group_locked(session, + ProcessGroup* group = team_get_process_group_locked(session, processGroupID); if (group == NULL) return B_BAD_VALUE; @@ -2549,7 +2532,7 @@ // terminal), there's a bit of signalling we have to do. if (team->session_id == team->id && team->group->session->controlling_tty >= 0) { - process_session* session = team->group->session; + ProcessSession* session = team->group->session; session->controlling_tty = -1; @@ -2563,7 +2546,7 @@ // stopped processes Team* child = team->children; while (child != NULL) { - process_group* childGroup = child->group; + ProcessGroup* childGroup = child->group; if (!childGroup->orphaned && update_orphaned_process_group(childGroup, team->id) && process_group_has_stopped_processes(childGroup)) { @@ -2579,7 +2562,7 @@ // update "orphaned" flags of all children's process groups Team* child = team->children; while (child != NULL) { - process_group* childGroup = child->group; + ProcessGroup* childGroup = child->group; if (!childGroup->orphaned) update_orphaned_process_group(childGroup, team->id); @@ -3613,10 +3596,10 @@ return EACCES; } - struct process_group* group = NULL; + ProcessGroup* group = NULL; if (groupID == processID) { // A new process group might be needed. - group = create_process_group(groupID); + group = new(std::nothrow) ProcessGroup(groupID); if (group == NULL) return B_NO_MEMORY; @@ -3626,7 +3609,7 @@ } status_t status = B_OK; - struct process_group* freeGroup = NULL; + ProcessGroup* freeGroup = NULL; InterruptsSpinLocker locker(gTeamSpinlock); @@ -3644,7 +3627,7 @@ freeGroup = group; } else { // Check if a process group with the requested ID already exists. - struct process_group* targetGroup + ProcessGroup* targetGroup = team_get_process_group_locked(team->group->session, groupID); if (targetGroup != NULL) { // In case of processID == groupID we have to free the @@ -3659,7 +3642,7 @@ if (targetGroup != NULL) { // we got a group, let's move the team there - process_group* oldGroup = team->group; + ProcessGroup* oldGroup = team->group; remove_team_from_group(team); insert_team_into_group(targetGroup, team); @@ -3702,10 +3685,10 @@ if (status != B_OK) { // in case of error, the group hasn't been added into the hash - team_delete_process_group(group); + delete group; } - team_delete_process_group(freeGroup); + delete freeGroup; return status == B_OK ? groupID : status; } @@ -3715,8 +3698,8 @@ _user_setsid(void) { Team* team = thread_get_current_thread()->team; - struct process_session* session; - struct process_group* group; + ProcessSession* session; + ProcessGroup* group; cpu_status state; bool failed = false; @@ -3724,13 +3707,13 @@ if (is_process_group_leader(team)) return B_NOT_ALLOWED; - group = create_process_group(team->id); + group = new(std::nothrow) ProcessGroup(team->id); if (group == NULL) return B_NO_MEMORY; - session = create_process_session(group->id); + session = new(std::nothrow) ProcessSession(group->id); if (session == NULL) { - team_delete_process_group(group); + delete group; return B_NO_MEMORY; } @@ -3750,8 +3733,8 @@ restore_interrupts(state); if (failed) { - team_delete_process_group(group); - free(session); + delete group; + delete session; return B_NOT_ALLOWED; }