diff options
author | Matthew Heon <matthew.heon@gmail.com> | 2018-08-08 12:26:01 -0400 |
---|---|---|
committer | Matthew Heon <matthew.heon@pm.me> | 2019-01-04 09:45:59 -0500 |
commit | 3ed81051e814e688f7b4ae1bbc7c4d4c3fbd7d0f (patch) | |
tree | 8b63f3390d82228b451e7832dd42d5f4d329cedf /libpod/lock/shm_lock_manager.go | |
parent | 185136cf0edee5288576b541517e0e994f6ee18d (diff) | |
download | podman-3ed81051e814e688f7b4ae1bbc7c4d4c3fbd7d0f.tar.gz podman-3ed81051e814e688f7b4ae1bbc7c4d4c3fbd7d0f.tar.bz2 podman-3ed81051e814e688f7b4ae1bbc7c4d4c3fbd7d0f.zip |
Add an SHM-backed Lock Manager implementation
Signed-off-by: Matthew Heon <matthew.heon@gmail.com>
Diffstat (limited to 'libpod/lock/shm_lock_manager.go')
-rw-r--r-- | libpod/lock/shm_lock_manager.go | 109 |
1 files changed, 109 insertions, 0 deletions
diff --git a/libpod/lock/shm_lock_manager.go b/libpod/lock/shm_lock_manager.go new file mode 100644 index 000000000..1fc2b106e --- /dev/null +++ b/libpod/lock/shm_lock_manager.go @@ -0,0 +1,109 @@ +package lock + +import ( + "fmt" + "math" + "strconv" + "syscall" + + "github.com/pkg/errors" +) + +// SHMLockManager manages shared memory locks. +type SHMLockManager struct { + locks *SHMLocks +} + +// NewSHMLockManager makes a new SHMLockManager with the given number of locks. +func NewSHMLockManager(numLocks uint32) (Manager, error) { + locks, err := 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) (LockManager, error) { + locks, err := 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 errors.Wrapf(err, "given ID %q is not a valid SHMLockManager ID - cannot be parsed as int", id) + } + + if intID < 0 { + return errors.Wrapf(syscall.EINVAL, "given ID %q is not a valid SHMLockManager ID - must be positive", id) + } + + if intID > math.MaxUint32 { + return 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.maxLocks { + return 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) +} |