@@ -491,83 +491,116 @@ _run_in_interpreter(PyInterpreterState *interp,
491491
492492/* "owned" interpreters *****************************************************/
493493
494- typedef _Py_hashtable_t owned_ids ;
495-
496- static Py_uhash_t
497- hash_int64 (const void * key )
498- {
499- #if sizeof (int64_t ) <= sizeof (Py_uhash_t )
500- return (Py_uhash_t )key ;
501- #else
502- int64_t val = * (int64_t * )key ;
503- return val % sizeof (Py_uhash_t );
504- #endif
505- }
494+ struct owned_id {
495+ int64_t id ;
496+ struct owned_id * next ;
497+ };
506498
507- static int
508- compare_int64 (const void * key1 , const void * key2 )
509- {
510- #if sizeof (int64_t ) <= sizeof (Py_uhash_t )
511- return (int64_t )key1 == (int64_t )key2 ;
512- #else
513- int64_t val1 = * (int64_t * )key1 ;
514- int64_t val2 = * (int64_t * )key2 ;
515- return val1 == val2 ;
516- #endif
517- }
499+ typedef struct {
500+ PyMutex mutex ;
501+ struct owned_id * head ;
502+ Py_ssize_t count ;
503+ } owned_ids ;
518504
519505static int
520506init_owned (owned_ids * owned )
521507{
522- _Py_hashtable_allocator_t alloc = (_Py_hashtable_allocator_t ){
523- .malloc = PyMem_RawMalloc ,
524- .free = PyMem_RawFree ,
525- };
526- _globals .owned = _Py_hashtable_new_full (
527- hash_int64 , compare_int64 , NULL , NULL , & alloc );
528- if (_globals .owned == NULL ) {
529- PyErr_NoMemory ();
530- return -1 ;
531- }
532508 return 0 ;
533509}
534510
535511static void
536512clear_owned (owned_ids * owned )
537513{
538- _Py_hashtable_destroy (owned );
514+ PyMutex_Lock (& owned -> mutex );
515+ struct owned_id * cur = owned -> head ;
516+ Py_ssize_t count = 0 ;
517+ while (cur != NULL ) {
518+ struct owned_id * next = cur -> next ;
519+ PyMem_RawFree (cur );
520+ cur = next ;
521+ count += 1 ;
522+ }
523+ assert (count == owned -> count );
524+ owned -> head = NULL ;
525+ owned -> count = 0 ;
526+ PyMutex_Unlock (& owned -> mutex );
539527}
540528
541- static int
529+ static struct owned_id *
530+ _find_owned (owned_ids * owned , int64_t interpid , struct owned_id * * p_prev )
531+ {
532+ // The caller must manage the lock.
533+ if (owned -> head == NULL ) {
534+ return NULL ;
535+ }
536+
537+ struct owned_id * prev = NULL ;
538+ struct owned_id * cur = owned -> head ;
539+ while (cur != NULL ) {
540+ if (cur -> id == interpid ) {
541+ break ;
542+ }
543+ prev = cur ;
544+ cur = cur -> next ;
545+ }
546+ if (cur == NULL ) {
547+ return NULL ;
548+ }
549+
550+ if (p_prev != NULL ) {
551+ * p_prev = prev ;
552+ }
553+ return cur ;
554+ }
555+
556+ static void
542557add_owned (owned_ids * owned , PyInterpreterState * interp )
543558{
559+ PyMutex_Lock (& owned -> mutex );
544560 int64_t id = PyInterpreterState_GetID (interp );
545- #if sizeof (int64_t ) <= sizeof (Py_uhash_t )
546- return _Py_hashtable_set (owned_ids , (const void * )id , 1 );
547- #else
548- assert (0 );
549- #endif
561+ struct owned_id * new = PyMem_RawMalloc (sizeof (struct owned_id ));
562+ assert (new != NULL );
563+ new -> id = id ;
564+ new -> next = owned -> head ;
565+ owned -> head = new ;
566+ owned -> count += 1 ;
567+ PyMutex_Unlock (& owned -> mutex );
550568}
551569
552570static void
553571drop_owned (owned_ids * owned , int64_t interpid )
554572{
555- #if sizeof (int64_t ) <= sizeof (Py_uhash_t )
556- _Py_hashtable_steal (owned_ids , (const void * )id );
557- #else
558- assert (0 );
559- #endif
573+ PyMutex_Lock (& owned -> mutex );
574+
575+ struct owned_id * prev ;
576+ struct owned_id * found = _find_owned (owned , interpid , & prev );
577+ if (found != NULL ) {
578+ if (prev == NULL ) {
579+ assert (found == owned -> head );
580+ owned -> head = found -> next ;
581+ }
582+ else {
583+ assert (found != owned -> head );
584+ prev -> next = found -> next ;
585+ }
586+ PyMem_RawFree (found );
587+ owned -> count -= 1 ;
588+ }
589+
590+ PyMutex_Unlock (& owned -> mutex );
560591}
561592
562593static int
563594is_owned (owned_ids * owned , PyInterpreterState * interp )
564595{
565- int64_t id = PyInterpreterState_GetID (interp );
566- #if sizeof (int64_t ) <= sizeof (Py_uhash_t )
567- return _Py_hashtable_get_entry (owned_ids , (const void * )id ) != NULL ;
568- #else
569- assert (0 );
570- #endif
596+ int64_t interpid = PyInterpreterState_GetID (interp );
597+ PyMutex_Lock (& owned -> mutex );
598+
599+ struct owned_id * found = _find_owned (owned , interpid , NULL );
600+ int res = found != NULL ;
601+
602+ PyMutex_Unlock (& owned -> mutex );
603+ return res ;
571604}
572605
573606
@@ -579,7 +612,7 @@ is_owned(owned_ids *owned, PyInterpreterState *interp)
579612static struct globals {
580613 PyMutex mutex ;
581614 int module_count ;
582- _Py_hashtable_t * owned ;
615+ owned_ids owned ;
583616} _globals = {0 };
584617
585618static int
0 commit comments