@@ -19,6 +19,8 @@ static struct comm_strs {
19
19
int capacity ;
20
20
} _comm_strs ;
21
21
22
+ static void comm_strs__remove_if_last (struct comm_str * cs );
23
+
22
24
static void comm_strs__init (void )
23
25
{
24
26
init_rwsem (& _comm_strs .lock );
@@ -58,22 +60,15 @@ static struct comm_str *comm_str__get(struct comm_str *cs)
58
60
59
61
static void comm_str__put (struct comm_str * cs )
60
62
{
61
- if (cs && refcount_dec_and_test (comm_str__refcnt (cs ))) {
62
- struct comm_strs * comm_strs = comm_strs__get ();
63
- int i ;
63
+ if (!cs )
64
+ return ;
64
65
65
- down_write (& comm_strs -> lock );
66
- for (i = 0 ; i < comm_strs -> num_strs ; i ++ ) {
67
- if (comm_strs -> strs [i ] == cs )
68
- break ;
69
- }
70
- for (; i < comm_strs -> num_strs - 1 ; i ++ )
71
- comm_strs -> strs [i ] = comm_strs -> strs [i + 1 ];
72
-
73
- comm_strs -> num_strs -- ;
74
- up_write (& comm_strs -> lock );
66
+ if (refcount_dec_and_test (comm_str__refcnt (cs ))) {
75
67
RC_CHK_FREE (cs );
76
68
} else {
69
+ if (refcount_read (comm_str__refcnt (cs )) == 1 )
70
+ comm_strs__remove_if_last (cs );
71
+
77
72
RC_CHK_PUT (cs );
78
73
}
79
74
}
@@ -107,6 +102,28 @@ static int comm_str__search(const void *_key, const void *_member)
107
102
return strcmp (key , comm_str__str (member ));
108
103
}
109
104
105
+ static void comm_strs__remove_if_last (struct comm_str * cs )
106
+ {
107
+ struct comm_strs * comm_strs = comm_strs__get ();
108
+
109
+ down_write (& comm_strs -> lock );
110
+ /*
111
+ * Are there only references from the array, if so remove the array
112
+ * reference under the write lock so that we don't race with findnew.
113
+ */
114
+ if (refcount_read (comm_str__refcnt (cs )) == 1 ) {
115
+ struct comm_str * * entry ;
116
+
117
+ entry = bsearch (comm_str__str (cs ), comm_strs -> strs , comm_strs -> num_strs ,
118
+ sizeof (struct comm_str * ), comm_str__search );
119
+ comm_str__put (* entry );
120
+ for (int i = entry - comm_strs -> strs ; i < comm_strs -> num_strs - 1 ; i ++ )
121
+ comm_strs -> strs [i ] = comm_strs -> strs [i + 1 ];
122
+ comm_strs -> num_strs -- ;
123
+ }
124
+ up_write (& comm_strs -> lock );
125
+ }
126
+
110
127
static struct comm_str * __comm_strs__find (struct comm_strs * comm_strs , const char * str )
111
128
{
112
129
struct comm_str * * result ;
@@ -158,7 +175,7 @@ static struct comm_str *comm_strs__findnew(const char *str)
158
175
}
159
176
}
160
177
up_write (& comm_strs -> lock );
161
- return result ;
178
+ return comm_str__get ( result ) ;
162
179
}
163
180
164
181
struct comm * comm__new (const char * str , u64 timestamp , bool exec )
0 commit comments