diff options
Diffstat (limited to 'libpod/lock/shm_lock_manager_linux.go')
-rw-r--r-- | libpod/lock/shm_lock_manager_linux.go | 112 |
1 files changed, 112 insertions, 0 deletions
diff --git a/libpod/lock/shm_lock_manager_linux.go b/libpod/lock/shm_lock_manager_linux.go new file mode 100644 index 000000000..b1e9df12d --- /dev/null +++ b/libpod/lock/shm_lock_manager_linux.go @@ -0,0 +1,112 @@ +// +build linux + +package lock + +import ( + "fmt" + "math" + "strconv" + "syscall" + + "github.com/pkg/errors" + "github.com/projectatomic/libpod/libpod/lock/shm" +) + +// SHMLockManager manages shared memory locks. +type SHMLockManager struct { + locks *shm.SHMLocks +} + +// NewSHMLockManager makes a new SHMLockManager with the given number of locks. +func NewSHMLockManager(numLocks uint32) (Manager, error) { + locks, err := shm.CreateSHMLock(numLocks) + if err != nil { + return nil, err + } + + manager := new(SHMLockManager) + manager.locks = locks + + return manager, nil +} + +// OpenSHMLockManager opens an existing SHMLockManager with the given number of +// locks. +func OpenSHMLockManager(numLocks uint32) (Manager, error) { + locks, err := shm.OpenSHMLock(numLocks) + if err != nil { + return nil, err + } + + manager := new(SHMLockManager) + manager.locks = locks + + return manager, nil +} + +// AllocateLock allocates a new lock from the manager. +func (m *SHMLockManager) AllocateLock() (Locker, error) { + semIndex, err := m.locks.AllocateSemaphore() + if err != nil { + return nil, err + } + + lock := new(SHMLock) + lock.lockID = semIndex + lock.manager = m + + return lock, nil +} + +// RetrieveLock retrieves a lock from the manager given its ID. +func (m *SHMLockManager) RetrieveLock(id string) (Locker, error) { + intID, err := strconv.ParseInt(id, 16, 64) + if err != nil { + return nil, errors.Wrapf(err, "given ID %q is not a valid SHMLockManager ID - cannot be parsed as int", id) + } + + if intID < 0 { + return nil, errors.Wrapf(syscall.EINVAL, "given ID %q is not a valid SHMLockManager ID - must be positive", id) + } + + if intID > math.MaxUint32 { + return nil, errors.Wrapf(syscall.EINVAL, "given ID %q is not a valid SHMLockManager ID - too large", id) + } + + var u32ID uint32 = uint32(intID) + if u32ID >= m.locks.GetMaxLocks() { + return nil, errors.Wrapf(syscall.EINVAL, "given ID %q is not a valid SHMLockManager ID - too large to fit", id) + } + + lock := new(SHMLock) + lock.lockID = u32ID + lock.manager = m + + return lock, nil +} + +// SHMLock is an individual shared memory lock. +type SHMLock struct { + lockID uint32 + manager *SHMLockManager +} + +// ID returns the ID of the lock. +func (l *SHMLock) ID() string { + return fmt.Sprintf("%x", l.lockID) +} + +// Lock acquires the lock. +func (l *SHMLock) Lock() error { + return l.manager.locks.LockSemaphore(l.lockID) +} + +// Unlock releases the lock. +func (l *SHMLock) Unlock() error { + return l.manager.locks.UnlockSemaphore(l.lockID) +} + +// Free releases the lock, allowing it to be reused. +func (l *SHMLock) Free() error { + return l.manager.locks.DeallocateSemaphore(l.lockID) +} |