[haiku-commits] r39860 - in haiku/trunk: headers/private/kernel src/system/kernel

  • From: ingo_weinhold@xxxxxx
  • To: haiku-commits@xxxxxxxxxxxxx
  • Date: Thu, 16 Dec 2010 02:15:35 +0100 (CET)

Author: bonefish
Date: 2010-12-16 02:15:35 +0100 (Thu, 16 Dec 2010)
New Revision: 39860
Changeset: http://dev.haiku-os.org/changeset/39860

Modified:
   haiku/trunk/headers/private/kernel/team.h
   haiku/trunk/headers/private/kernel/thread_types.h
   haiku/trunk/src/system/kernel/team.cpp
Log:
* Implemented a generic way to associate data with a team which is
  automatically cleaned up when the team is deleted: Class AssociatedData is
  the base class for a data item, AssociatedDataOwner a container for them
  (struct team derives from it). Functions team_associate_data() and
  team_dissociate_data() add/remove data.
* Turned sTeamHash into a BOpenHashTable (necessary since struct team is no
  longer a POD).


Modified: haiku/trunk/headers/private/kernel/team.h
===================================================================
--- haiku/trunk/headers/private/kernel/team.h   2010-12-15 23:18:13 UTC (rev 
39859)
+++ haiku/trunk/headers/private/kernel/team.h   2010-12-16 01:15:35 UTC (rev 
39860)
@@ -63,6 +63,9 @@
 struct user_thread* team_allocate_user_thread(struct team* team);
 void team_free_user_thread(struct thread* thread);
 
+bool team_associate_data(AssociatedData* data);
+bool team_dissociate_data(AssociatedData* data);
+
 // used in syscalls.c
 thread_id _user_load_image(const char* const* flatArgs, size_t flatArgsSize,
                        int32 argCount, int32 envCount, int32 priority, uint32 
flags,

Modified: haiku/trunk/headers/private/kernel/thread_types.h
===================================================================
--- haiku/trunk/headers/private/kernel/thread_types.h   2010-12-15 23:18:13 UTC 
(rev 39859)
+++ haiku/trunk/headers/private/kernel/thread_types.h   2010-12-16 01:15:35 UTC 
(rev 39860)
@@ -10,8 +10,11 @@
 
 #ifndef _ASSEMBLER
 
+#include <Referenceable.h>
+
 #include <arch/thread_types.h>
 #include <condition_variable.h>
+#include <lock.h>
 #include <signal.h>
 #include <smp.h>
 #include <thread_defs.h>
@@ -58,6 +61,7 @@
 struct image;                                  // defined in image.c
 struct io_context;
 struct realtime_sem_context;   // defined in realtime_sem.cpp
+struct scheduler_thread_data;
 struct select_info;
 struct user_thread;                            // defined in 
libroot/user_thread.h
 struct xsi_sem_context;                        // defined in xsi_semaphore.cpp
@@ -154,9 +158,48 @@
        struct user_thread*                     thread;
 };
 
-struct scheduler_thread_data;
 
-struct team {
+class AssociatedDataOwner;
+
+class AssociatedData : public Referenceable,
+       public DoublyLinkedListLinkImpl<AssociatedData> {
+public:
+                                                               
AssociatedData();
+       virtual                                         ~AssociatedData();
+
+                       AssociatedDataOwner* Owner() const
+                                                                       { 
return fOwner; }
+                       void                            
SetOwner(AssociatedDataOwner* owner)
+                                                                       { 
fOwner = owner; }
+
+       virtual void                            
OwnerDeleted(AssociatedDataOwner* owner);
+
+private:
+                       AssociatedDataOwner* fOwner;
+};
+
+
+class AssociatedDataOwner {
+public:
+                                                               
AssociatedDataOwner();
+                                                               
~AssociatedDataOwner();
+
+                       bool                            AddData(AssociatedData* 
data);
+                       bool                            
RemoveData(AssociatedData* data);
+
+                       void                            PrepareForDeletion();
+
+private:
+                       typedef DoublyLinkedList<AssociatedData> DataList;
+
+private:
+
+                       mutex                           fLock;
+                       DataList                        fList;
+};
+
+
+struct team : AssociatedDataOwner {
        struct team             *next;                  // next in hash
        struct team             *siblings_next;
        struct team             *parent;

Modified: haiku/trunk/src/system/kernel/team.cpp
===================================================================
--- haiku/trunk/src/system/kernel/team.cpp      2010-12-15 23:18:13 UTC (rev 
39859)
+++ haiku/trunk/src/system/kernel/team.cpp      2010-12-16 01:15:35 UTC (rev 
39860)
@@ -100,7 +100,35 @@
 };
 
 
-static hash_table* sTeamHash = NULL;
+struct TeamHashDefinition {
+       typedef team_id         KeyType;
+       typedef struct team     ValueType;
+
+       size_t HashKey(team_id key) const
+       {
+               return key;
+       }
+
+       size_t Hash(struct team* value) const
+       {
+               return HashKey(value->id);
+       }
+
+       bool Compare(team_id key, struct team* value) const
+       {
+               return value->id == key;
+       }
+
+       struct team*& GetLink(struct team* value) const
+       {
+               return value->next;
+       }
+};
+
+typedef BOpenHashTable<TeamHashDefinition> TeamHashTable;
+
+
+static TeamHashTable sTeamHash;
 static hash_table* sGroupHash = NULL;
 static struct team* sKernelTeam = NULL;
 
@@ -368,8 +396,6 @@
 static int
 dump_team_info(int argc, char** argv)
 {
-       struct hash_iterator iterator;
-       struct team* team;
        team_id id = -1;
        bool found = false;
 
@@ -390,8 +416,8 @@
        }
 
        // walk through the thread list, trying to match name or id
-       hash_open(sTeamHash, &iterator);
-       while ((team = (struct team*)hash_next(sTeamHash, &iterator)) != NULL) {
+       for (TeamHashTable::Iterator it = sTeamHash.GetIterator();
+               struct team* team = it.Next();) {
                if ((team->name && strcmp(argv[1], team->name) == 0)
                        || team->id == id) {
                        _dump_team_info(team);
@@ -399,7 +425,6 @@
                        break;
                }
        }
-       hash_close(sTeamHash, &iterator, false);
 
        if (!found)
                kprintf("team \"%s\" (%ld) doesn't exist!\n", argv[1], id);
@@ -410,48 +435,18 @@
 static int
 dump_teams(int argc, char** argv)
 {
-       struct hash_iterator iterator;
-       struct team* team;
-
        kprintf("team           id  parent      name\n");
-       hash_open(sTeamHash, &iterator);
 
-       while ((team = (struct team*)hash_next(sTeamHash, &iterator)) != NULL) {
+       for (TeamHashTable::Iterator it = sTeamHash.GetIterator();
+               struct team* team = it.Next();) {
                kprintf("%p%7ld  %p  %s\n", team, team->id, team->parent, 
team->name);
        }
 
-       hash_close(sTeamHash, &iterator, false);
        return 0;
 }
 
 
 static int
-team_struct_compare(void* _p, const void* _key)
-{
-       struct team* p = (struct team*)_p;
-       const struct team_key* key = (const struct team_key*)_key;
-
-       if (p->id == key->id)
-               return 0;
-
-       return 1;
-}
-
-
-static uint32
-team_struct_hash(void* _p, const void* _key, uint32 range)
-{
-       struct team* p = (struct team*)_p;
-       const struct team_key* key = (const struct team_key*)_key;
-
-       if (p != NULL)
-               return p->id % range;
-
-       return (uint32)key->id % range;
-}
-
-
-static int
 process_group_compare(void* _group, const void* _key)
 {
        struct process_group* group = (struct process_group*)_group;
@@ -742,10 +737,10 @@
 static struct team*
 create_team_struct(const char* name, bool kernel)
 {
-       struct team* team = (struct team*)malloc(sizeof(struct team));
+       struct team* team = new(std::nothrow) struct team;
        if (team == NULL)
                return NULL;
-       MemoryDeleter teamDeleter(team);
+       ObjectDeleter<struct team> teamDeleter(team);
 
        team->next = team->siblings_next = team->children = team->parent = NULL;
        team->id = allocate_thread_id();
@@ -840,6 +835,9 @@
 static void
 delete_team_struct(struct team* team)
 {
+       // get rid of all associated data
+       team->PrepareForDeletion();
+
        while (death_entry* threadDeathEntry = 
(death_entry*)list_remove_head_item(
                        &team->dead_threads)) {
                free(threadDeathEntry);
@@ -860,7 +858,7 @@
        delete team->continued_children;
        delete team->stopped_children;
        delete team->dead_children;
-       free(team);
+       delete team;
 }
 
 
@@ -1206,7 +1204,7 @@
        // inherit the parent's user/group
        inherit_parent_user_and_group_locked(team, parent);
 
-       hash_insert(sTeamHash, team);
+       sTeamHash.InsertUnchecked(team);
        insert_team_into_parent(parent, team);
        insert_team_into_group(parent->group, team);
        sUsedTeams++;
@@ -1331,7 +1329,7 @@
 
        remove_team_from_group(team);
        remove_team_from_parent(team->parent, team);
-       hash_remove(sTeamHash, team);
+       sTeamHash.RemoveUnchecked(team);
 
        RELEASE_TEAM_LOCK();
        restore_interrupts(state);
@@ -1546,7 +1544,7 @@
        // Inherit the parent's user/group.
        inherit_parent_user_and_group_locked(team, parentTeam);
 
-       hash_insert(sTeamHash, team);
+       sTeamHash.InsertUnchecked(team);
        insert_team_into_parent(parentTeam, team);
        insert_team_into_group(parentTeam->group, team);
        sUsedTeams++;
@@ -1687,7 +1685,7 @@
 
        remove_team_from_group(team);
        remove_team_from_parent(parentTeam, team);
-       hash_remove(sTeamHash, team);
+       sTeamHash.RemoveUnchecked(team);
 
        teamLocker.Unlock();
 
@@ -2058,8 +2056,9 @@
        struct process_group* group;
 
        // create the team hash table
-       sTeamHash = hash_init(16, offsetof(struct team, next),
-               &team_struct_compare, &team_struct_hash);
+       new(&sTeamHash) TeamHashTable;
+       if (sTeamHash.Init(32) != B_OK)
+               panic("Failed to init team hash table!");
 
        sGroupHash = hash_init(16, offsetof(struct process_group, next),
                &process_group_compare, &process_group_hash);
@@ -2099,7 +2098,7 @@
                panic("could not create io_context for kernel team!\n");
 
        // stick it in the team hash
-       hash_insert(sTeamHash, sKernelTeam);
+       sTeamHash.InsertUnchecked(sKernelTeam);
 
        add_debugger_command_etc("team", &dump_team_info,
                "Dump info about a particular team",
@@ -2138,18 +2137,13 @@
 struct team*
 team_iterate_through_teams(team_iterator_callback callback, void* cookie)
 {
-       struct hash_iterator iterator;
-       hash_open(sTeamHash, &iterator);
-
-       struct team* team;
-       while ((team = (struct team*)hash_next(sTeamHash, &iterator)) != NULL) {
+       for (TeamHashTable::Iterator it = sTeamHash.GetIterator();
+               struct team* team = it.Next();) {
                if (callback(team, cookie))
-                       break;
+                       return team;
        }
 
-       hash_close(sTeamHash, &iterator, false);
-
-       return team;
+       return NULL;
 }
 
 
@@ -2204,10 +2198,7 @@
 struct team*
 team_get_team_struct_locked(team_id id)
 {
-       struct team_key key;
-       key.id = id;
-
-       return (struct team*)hash_lookup(sTeamHash, &key);
+       return sTeamHash.Lookup(id);
 }
 
 
@@ -2331,7 +2322,7 @@
        // mutex_lock_threads_lock(<team related lock>), as used in the VFS 
code to
        // lock another team's IO context.
        GRAB_THREAD_LOCK();
-       hash_remove(sTeamHash, team);
+       sTeamHash.RemoveUnchecked(team);
        RELEASE_THREAD_LOCK();
        sUsedTeams--;
 
@@ -2825,6 +2816,127 @@
 }
 
 
+//     #pragma mark - Associated data interface
+
+
+AssociatedData::AssociatedData()
+       :
+       fOwner(NULL)
+{
+}
+
+
+AssociatedData::~AssociatedData()
+{
+}
+
+
+void
+AssociatedData::OwnerDeleted(AssociatedDataOwner* owner)
+{
+}
+
+
+AssociatedDataOwner::AssociatedDataOwner()
+{
+       mutex_init(&fLock, "associated data owner");
+}
+
+
+AssociatedDataOwner::~AssociatedDataOwner()
+{
+       mutex_destroy(&fLock);
+}
+
+
+bool
+AssociatedDataOwner::AddData(AssociatedData* data)
+{
+       MutexLocker locker(fLock);
+
+       if (data->Owner() != NULL)
+               return false;
+
+       data->AcquireReference();
+       fList.Add(data);
+       data->SetOwner(this);
+
+       return true;
+}
+
+
+bool
+AssociatedDataOwner::RemoveData(AssociatedData* data)
+{
+       MutexLocker locker(fLock);
+
+       if (data->Owner() != this)
+               return false;
+
+       data->SetOwner(NULL);
+       fList.Remove(data);
+
+       locker.Unlock();
+
+       data->ReleaseReference();
+
+       return true;
+}
+
+
+void
+AssociatedDataOwner::PrepareForDeletion()
+{
+       MutexLocker locker(fLock);
+
+       // move all data to a temporary list and unset the owner
+       DataList list;
+       list.MoveFrom(&fList);
+
+       for (DataList::Iterator it = list.GetIterator();
+               AssociatedData* data = it.Next();) {
+               data->SetOwner(NULL);
+       }
+
+       locker.Unlock();
+
+       // call the notification hooks and release our references
+       while (AssociatedData* data = list.RemoveHead()) {
+               data->OwnerDeleted(this);
+               data->ReleaseReference();
+       }
+}
+
+
+/*!    Associates data with the current team.
+       When the team is deleted, the data object is notified.
+       The team acquires a reference to the object.
+
+       \param data The data object.
+       \return \c true on success, \c false otherwise. Fails only when the 
supplied
+               data object is already associated with another owner.
+*/
+bool
+team_associate_data(AssociatedData* data)
+{
+       return thread_get_current_thread()->team->AddData(data);
+}
+
+
+/*!    Dissociates data from the current team.
+       Balances an earlier call to team_associate_data().
+
+       \param data The data object.
+       \return \c true on success, \c false otherwise. Fails only when the data
+               object is not associated with the current team.
+*/
+bool
+team_dissociate_data(AssociatedData* data)
+{
+       return thread_get_current_thread()->team->RemoveData(data);
+}
+
+
 //     #pragma mark - Public kernel API
 
 


Other related posts:

  • » [haiku-commits] r39860 - in haiku/trunk: headers/private/kernel src/system/kernel - ingo_weinhold