Author: bonefish Date: 2011-05-04 01:46:53 +0200 (Wed, 04 May 2011) New Revision: 41315 Changeset: https://dev.haiku-os.org/changeset/41315 Modified: haiku/branches/developer/bonefish/signals/headers/private/kernel/thread_types.h haiku/branches/developer/bonefish/signals/src/system/kernel/team.cpp Log: * Derived ProcessSession and ProcessGroup from BReferenceable and got rid of their respective reference count (group_count, refs). * Made ProcessGroup::session private, renamed it to fSession, and added a getter (Session()) and an extended setter (Publish()). * Got rid of the now superfluous insert_group_into_session(), remove_group_from_session(), acquire_process_group_ref(), release_process_group_ref(). * _user_setsid(): Added TODO. 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:59:49 UTC (rev 41314) +++ haiku/branches/developer/bonefish/signals/headers/private/kernel/thread_types.h 2011-05-03 23:46:53 UTC (rev 41315) @@ -412,9 +412,8 @@ }; -struct ProcessSession { +struct ProcessSession : BReferenceable { pid_t id; - int32 group_count; int32 controlling_tty; // index of the controlling tty, // -1 if none pid_t foreground_group; @@ -433,11 +432,9 @@ }; -struct ProcessGroup : DeferredDeletable { +struct ProcessGroup : DeferredDeletable, BReferenceable { struct ProcessGroup *next; // next in hash - struct ProcessSession *session; pid_t id; - int32 refs; BKernel::Team *teams; bool orphaned; @@ -450,8 +447,16 @@ void Unlock() { mutex_unlock(&fLock); } + ProcessSession* Session() const + { return fSession; } + void Publish(ProcessSession* session); + +protected: + virtual void LastReferenceReleased(); + private: mutex fLock; + ProcessSession* fSession; }; } // namespace BKernel 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:59:49 UTC (rev 41314) +++ haiku/branches/developer/bonefish/signals/src/system/kernel/team.cpp 2011-05-03 23:46:53 UTC (rev 41315) @@ -739,11 +739,10 @@ ProcessGroup::ProcessGroup(pid_t id) : - session(NULL), id(id), - refs(0), teams(NULL), - orphaned(true) + orphaned(true), + fSession(NULL) { char lockName[32]; snprintf(lockName, sizeof(lockName), "Group:%" B_PRId32, id); @@ -755,25 +754,43 @@ { 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; + if (fSession != NULL) { + sGroupHash.RemoveUnchecked(this); + fSession->ReleaseReference(); } mutex_destroy(&fLock); } +/*! Adds the group the given session and makes it publicly accessible. + The teams lock must be held. +*/ +void +ProcessGroup::Publish(ProcessSession* session) +{ + fSession = session; + sGroupHash.InsertUnchecked(this); + session->AcquireReference(); +} + + +void +ProcessGroup::LastReferenceReleased() +{ + if (are_interrupts_enabled()) + delete this; + else + deferred_delete(this); +} + + // #pragma mark - ProcessSession ProcessSession::ProcessSession(pid_t id) : id(id), - group_count(0), controlling_tty(-1), foreground_group(-1) { @@ -949,93 +966,17 @@ } -/*! 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(ProcessGroup* group) -{ - ProcessSession* session = group->session; - - // the group must be in any session to let this function have any effect - if (session == NULL) - return; - - 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() - if (--session->group_count > 0) - group->session = NULL; -} - - -/*! Team lock must be held. -*/ -static void -acquire_process_group_ref(pid_t groupID) -{ - ProcessGroup* group = team_get_process_group_locked(NULL, groupID); - if (group == NULL) { - panic("acquire_process_group_ref(): unknown group ID: %ld", groupID); - return; - } - - group->refs++; -} - - -/*! Team lock must be held. -*/ -static void -release_process_group_ref(pid_t groupID) -{ - ProcessGroup* group = team_get_process_group_locked(NULL, groupID); - if (group == NULL) { - panic("release_process_group_ref(): unknown group ID: %ld", groupID); - return; - } - - if (group->refs <= 0) { - panic("release_process_group_ref(%ld): ref count already 0", groupID); - return; - } - - if (--group->refs > 0) - return; - - // group is no longer used - - remove_group_from_session(group); - deferred_delete(group); -} - - /*! You must hold the team lock when calling this function. */ static void -insert_group_into_session(ProcessSession* session, ProcessGroup* group) -{ - if (group == NULL) - return; - - group->session = session; - sGroupHash.InsertUnchecked(group); - session->group_count++; -} - - -/*! You must hold the team lock when calling this function. */ -static void insert_team_into_group(ProcessGroup* group, Team* team) { team->group = group; team->group_id = group->id; - team->session_id = group->session->id; + team->session_id = group->Session()->id; team->group_next = group->teams; group->teams = team; - acquire_process_group_ref(group->id); + group->AcquireReference(); } @@ -1071,7 +1012,7 @@ team->group = NULL; team->group_next = NULL; - release_process_group_ref(group->id); + group->ReleaseReference(); } @@ -1920,7 +1861,7 @@ Team* team; ProcessGroup* group = team_get_process_group_locked( - parent->group->session, groupID); + parent->group->Session(), groupID); if (group == NULL) return false; @@ -1982,7 +1923,17 @@ { if (has_group_ref) { InterruptsSpinLocker locker(gTeamSpinlock); - release_process_group_ref(group_id); + + ProcessGroup* group = team_get_process_group_locked(NULL, group_id); + if (group == NULL) { + panic("job_control_entry::~job_control_entry(): unknown group " + "ID: %ld", group_id); + return; + } + + locker.Unlock(); + + group->ReleaseReference(); } } @@ -1993,15 +1944,16 @@ job_control_entry::InitDeadState() { if (team != NULL) { - Thread* thread = team->main_thread; group_id = team->group_id; + team->group->AcquireReference(); + has_group_ref = true; + + Thread* thread = team->main_thread; this->thread = thread->id; status = thread->exit.status; reason = thread->exit.reason; signal = thread->exit.signal; team = NULL; - acquire_process_group_ref(group_id); - has_group_ref = true; } } @@ -2235,7 +2187,7 @@ if (team->id != dyingProcess && parent != NULL && parent->id != dyingProcess && parent->group_id != group->id - && parent->session_id == group->session->id) { + && parent->session_id == group->Session()->id) { return false; } @@ -2290,12 +2242,14 @@ session = new(std::nothrow) ProcessSession(1); if (session == NULL) panic("Could not create initial session.\n"); + BReference<ProcessSession> sessionReference(session, true); group = new(std::nothrow) ProcessGroup(1); if (group == NULL) panic("Could not create initial process group.\n"); + BReference<ProcessGroup> groupReference(group, true); - insert_group_into_session(session, group); + group->Publish(session); // create the kernel team sKernelTeam = Team::Create("kernel_team", true); @@ -2433,7 +2387,7 @@ team_get_process_group_locked(ProcessSession* session, pid_t id) { ProcessGroup* group = sGroupHash.Lookup(id); - if (group != NULL && (session == NULL || session == group->session)) + if (group != NULL && (session == NULL || session == group->Session())) return group; return NULL; @@ -2447,8 +2401,8 @@ InterruptsSpinLocker _(gTeamSpinlock); - team->group->session->controlling_tty = ttyIndex; - team->group->session->foreground_group = -1; + team->group->Session()->controlling_tty = ttyIndex; + team->group->Session()->foreground_group = -1; } @@ -2459,7 +2413,7 @@ InterruptsSpinLocker _(gTeamSpinlock); - return team->group->session->controlling_tty; + return team->group->Session()->controlling_tty; } @@ -2471,7 +2425,7 @@ InterruptsSpinLocker locker(gTeamSpinlock); - ProcessSession* session = team->group->session; + ProcessSession* session = team->group->Session(); // must be the controlling tty of the calling process if (session->controlling_tty != ttyIndex) @@ -2495,7 +2449,7 @@ return B_INTERRUPTED; } - team->group->session->foreground_group = processGroupID; + team->group->Session()->foreground_group = processGroupID; return B_OK; } @@ -2531,8 +2485,8 @@ // If we're a controlling process (i.e. a session leader with controlling // terminal), there's a bit of signalling we have to do. if (team->session_id == team->id - && team->group->session->controlling_tty >= 0) { - ProcessSession* session = team->group->session; + && team->group->Session()->controlling_tty >= 0) { + ProcessSession* session = team->group->Session(); session->controlling_tty = -1; @@ -3607,9 +3561,9 @@ // below. group->orphaned = true; } + BReference<ProcessGroup> groupReference(group, true); status_t status = B_OK; - ProcessGroup* freeGroup = NULL; InterruptsSpinLocker locker(gTeamSpinlock); @@ -3624,19 +3578,17 @@ status = EACCES; } else if (team->group_id == groupID) { // the team is already in the desired process group - freeGroup = group; } else { // Check if a process group with the requested ID already exists. - ProcessGroup* targetGroup - = team_get_process_group_locked(team->group->session, groupID); + ProcessGroup* targetGroup = team_get_process_group_locked( + team->group->Session(), groupID); if (targetGroup != NULL) { // In case of processID == groupID we have to free the // allocated group. - freeGroup = group; } else if (processID == groupID) { // We created a new process group, let us insert it into the // team's session. - insert_group_into_session(team->group->session, group); + group->Publish(team->group->Session()); targetGroup = group; } @@ -3683,13 +3635,6 @@ locker.Unlock(); - if (status != B_OK) { - // in case of error, the group hasn't been added into the hash - delete group; - } - - delete freeGroup; - return status == B_OK ? groupID : status; } @@ -3710,12 +3655,12 @@ group = new(std::nothrow) ProcessGroup(team->id); if (group == NULL) return B_NO_MEMORY; + BReference<ProcessGroup> groupReference(group, true); session = new(std::nothrow) ProcessSession(group->id); - if (session == NULL) { - delete group; + if (session == NULL) return B_NO_MEMORY; - } + BReference<ProcessSession> sessionReference(session, true); state = disable_interrupts(); GRAB_TEAM_LOCK(); @@ -3724,19 +3669,22 @@ if (!is_process_group_leader(team)) { remove_team_from_group(team); - insert_group_into_session(session, group); + group->Publish(session); insert_team_into_group(group, team); + + // TODO: We need to update the orphaned state of children's process + // groups. If a child was in our process group or in another session + // nothing will change for its process group, but if it was in another + // process group of the same session, that process group might now be + // orphaned. } else failed = true; RELEASE_TEAM_LOCK(); restore_interrupts(state); - if (failed) { - delete group; - delete session; + if (failed) return B_NOT_ALLOWED; - } return team->group_id; }