Changeset 18622

Show
Ignore:
Timestamp:
08/24/06 18:58:48 (2 years ago)
Author:
axeld
Message:

Process groups are no longer searched via their team/session, but by using a separate
hash. This also allows them to stay valid after the group leader died when there are
other teams left in it. This closes bug #1.

Location:
haiku/trunk
Files:
2 modified

Legend:

Unmodified
Added
Removed
  • haiku/trunk/headers/private/kernel/thread_types.h

    r18543 r18622  
    5858struct process_session { 
    5959        pid_t                           id; 
    60         struct list                     groups; 
     60        int32                           group_count; 
    6161}; 
    6262 
    6363struct process_group { 
    64         struct list_link        link; 
     64        struct process_group *next;     // next in hash 
    6565        struct process_session *session; 
    6666        pid_t                           id; 
     
    8787 
    8888struct team { 
    89         struct team             *next;                  /* next team in the hash */ 
     89        struct team             *next;                  // next in hash 
    9090        struct team             *siblings_next; 
    9191        struct team             *parent; 
  • haiku/trunk/src/system/kernel/team.c

    r18621 r18622  
    6464 
    6565 
    66 // team list 
    6766static void *sTeamHash = NULL; 
     67static void *sGroupHash = NULL; 
    6868static struct team *sKernelTeam = NULL; 
    6969 
     
    8383static int team_struct_compare(void *_p, const void *_key); 
    8484static uint32 team_struct_hash(void *_p, const void *_key, uint32 range); 
     85static int process_group_compare(void *_p, const void *_key); 
     86static uint32 process_group_hash(void *_p, const void *_key, uint32 range); 
    8587static void free_strings_array(char **strings, int32 count); 
    8688static status_t user_copy_strings_array(char * const *strings, int32 count, char ***_strings); 
     
    176178 
    177179        // create the team hash table 
    178         sTeamHash = hash_init(15, offsetof(struct team, next), 
     180        sTeamHash = hash_init(16, offsetof(struct team, next), 
    179181                &team_struct_compare, &team_struct_hash); 
     182 
     183        sGroupHash = hash_init(16, offsetof(struct process_group, next), 
     184                &process_group_compare, &process_group_hash); 
    180185 
    181186        // create initial session and process groups 
     
    362367 
    363368 
     369static int 
     370process_group_compare(void *_group, const void *_key) 
     371{ 
     372        struct process_group *group = _group; 
     373        const struct team_key *key = _key; 
     374 
     375        if (group->id == key->id) 
     376                return 0; 
     377 
     378        return 1; 
     379} 
     380 
     381 
     382static uint32 
     383process_group_hash(void *_group, const void *_key, uint32 range) 
     384{ 
     385        struct process_group *group = _group; 
     386        const struct team_key *key = _key; 
     387 
     388        if (group != NULL) 
     389                return group->id % range; 
     390 
     391        return (uint32)key->id % range; 
     392} 
     393 
     394 
    364395/** Quick check to see if we have a valid team ID. 
    365396 */ 
     
    390421{ 
    391422        struct team_key key; 
    392  
    393423        key.id = id; 
    394424 
     
    483513 
    484514 
     515/**     You must hold the team lock when calling this function. */ 
     516 
    485517static void 
    486518insert_group_into_session(struct process_session *session, struct process_group *group) 
     
    490522 
    491523        group->session = session; 
    492         list_add_link_to_tail(&session->groups, group); 
    493 } 
    494  
     524        hash_insert(sGroupHash, group); 
     525        session->group_count++; 
     526} 
     527 
     528 
     529/**     You must hold the team lock when calling this function. */ 
    495530 
    496531static void 
     
    521556                return; 
    522557 
    523         list_remove_link(group); 
     558        hash_remove(sGroupHash, group); 
    524559 
    525560        // we cannot free the resource here, so we're keeping the group link 
    526561        // around - this way it'll be freed by free_process_group() 
    527         if (!list_is_empty(&session->groups)) 
     562        if (--session->group_count > 0) 
    528563                group->session = NULL; 
    529564} 
     
    633668 
    634669        session->id = id; 
    635         list_init(&session->groups); 
     670        session->group_count = 0; 
    636671 
    637672        return session; 
     
    15181553get_process_group_locked(struct team *team, pid_t id) 
    15191554{ 
    1520         struct list *groups = &team->group->session->groups; 
    1521         struct process_group *group = NULL; 
    1522          
    1523         // ToDo: a process group lasts as long as its last member - and 
    1524         //      that doesn't have to be the process leader. IOW we need 
    1525         //      a separate hash table for those groups without a leader. 
    1526  
    1527         // a short cut when the current team's group is asked for 
    1528         if (team->group->id == id) 
    1529                 return team->group; 
    1530  
    1531         while ((group = list_get_next_item(groups, group)) != NULL) { 
    1532                 if (group->id == id) 
    1533                         return group; 
    1534         } 
     1555        struct process_group *group; 
     1556        struct team_key key; 
     1557        key.id = id; 
     1558 
     1559        group = (struct process_group *)hash_lookup(sGroupHash, &key); 
     1560        if (group != NULL && team->group->session == group->session) 
     1561                return group; 
    15351562 
    15361563        return NULL; 
     
    23382365                        insert_team_into_group(group, team); 
    23392366                } else { 
    2340                         struct process_session *session = team->group->session; 
    2341                         struct process_group *group = NULL; 
    2342  
    23432367                        // check if this team can have the group ID; there must be one matching 
    23442368                        // process ID in the team's session 
    23452369 
    2346                         while ((group = list_get_next_item(&session->groups, group)) != NULL) { 
    2347                                 if (group->id == groupID) 
    2348                                         break; 
    2349                         } 
    2350  
     2370                        struct process_group *group = get_process_group_locked(team, groupID); 
    23512371                        if (group) { 
    23522372                                // we got a group, let's move the team there 
     
    23622382        restore_interrupts(state); 
    23632383 
    2364         if (status != B_OK && group != NULL) 
     2384        if (status != B_OK && group != NULL) { 
     2385                // in case of error, the group hasn't been added into the hash 
    23652386                team_delete_process_group(group); 
     2387        } 
    23662388 
    23672389        team_delete_process_group(freeGroup);