@@ -338,6 +338,17 @@ def for_each_rwsem_waiter_entity(rwsem: Object) -> Iterable[Object]:
338338 yield waiter
339339
340340
341+ def rwsem_count (rwsem : Object ) -> int :
342+ try :
343+ return rwsem .count .counter .value_ ()
344+ except AttributeError :
345+ # For all modern kernels, rwsem.count is an atomic_long_t. Prior to
346+ # 8ee62b1870be8 ("locking/rwsem: Convert sem->count to
347+ # 'atomic_long_t'"), which was merged in 4.8, it was a long. It's not
348+ # too hard to fall back.
349+ return rwsem .count .value_ ()
350+
351+
341352def get_rwsem_owner (rwsem : Object ) -> Tuple [Object , "RwsemStateCode" ]:
342353 """
343354 Find owner of given rwsem
@@ -346,7 +357,7 @@ def get_rwsem_owner(rwsem: Object) -> Tuple[Object, "RwsemStateCode"]:
346357 :returns: type of owner and ``struct task_struct *`` if owner can be found, NULL otherwise
347358 """
348359 prog = rwsem .prog_
349- if not rwsem . count . counter . value_ ( ):
360+ if not rwsem_count ( rwsem ):
350361 return NULL (prog , "struct task_struct *" ), RwsemStateCode .UNLOCKED
351362
352363 if is_rwsem_writer_owned (rwsem ):
@@ -461,12 +472,13 @@ def is_rwsem_reader_owned(rwsem: Object) -> bool:
461472 case when type of owner could not be determined or when rwsem
462473 is free.)
463474 """
464- if not rwsem .count .counter .value_ (): # rwsem is free
475+ count = rwsem_count (rwsem )
476+ if not count : # rwsem is free
465477 return False
466478 if rwsem .owner .type_ .type_name () == "atomic_long_t" :
467- owner_is_writer = rwsem . count . counter . value_ () & _RWSEM_WRITER_LOCKED
479+ owner_is_writer = count & _RWSEM_WRITER_LOCKED
468480 owner_is_reader = (
469- (rwsem . count . counter . value_ () & _RWSEM_READER_MASK )
481+ (count & _RWSEM_READER_MASK )
470482 and (rwsem .owner .counter .value_ () & _RWSEM_READER_OWNED )
471483 and (owner_is_writer == 0 )
472484 )
@@ -491,11 +503,12 @@ def is_rwsem_writer_owned(rwsem: Object) -> bool:
491503 case when type of owner could not be determined or when rwsem
492504 was free.)
493505 """
494- if not rwsem .count .counter .value_ (): # rwsem is free
506+ count = rwsem_count (rwsem )
507+ if not count : # rwsem is free
495508 return False
496509
497510 if rwsem .owner .type_ .type_name () == "atomic_long_t" :
498- owner_is_writer = rwsem . count . counter . value_ () & _RWSEM_WRITER_LOCKED
511+ owner_is_writer = count & _RWSEM_WRITER_LOCKED
499512 return bool (owner_is_writer )
500513 else :
501514 if not rwsem .owner .value_ ():
@@ -536,7 +549,8 @@ def get_rwsem_info(rwsem: Object, callstack: int = 0) -> None:
536549 # of rwsem ->count and ->owner bits.
537550
538551 print (f"({ rwsem .type_ .type_name ()} )0x{ rwsem .value_ ():x} " )
539- if not rwsem .count .counter .value_ ():
552+ count = rwsem_count (rwsem )
553+ if not count :
540554 print ("rwsem is free." )
541555 return
542556
@@ -557,7 +571,7 @@ def get_rwsem_info(rwsem: Object, callstack: int = 0) -> None:
557571 # So try to retrieve that info.
558572 if rwsem .owner .type_ .type_name () == "atomic_long_t" :
559573 num_readers = (
560- rwsem . count . counter . value_ () & _RWSEM_READER_MASK
574+ count & _RWSEM_READER_MASK
561575 ) >> _RWSEM_READER_SHIFT
562576 print (f"Owned by { num_readers } reader(s)" )
563577 else :
0 commit comments