podman

Форк
0
/
shm_lock_manager_linux.go 
142 строки · 3.3 Кб
1
//go:build linux
2

3
package lock
4

5
import (
6
	"fmt"
7
	"syscall"
8

9
	"github.com/containers/podman/v5/libpod/lock/shm"
10
)
11

12
// SHMLockManager manages shared memory locks.
13
type SHMLockManager struct {
14
	locks *shm.SHMLocks
15
}
16

17
// NewSHMLockManager makes a new SHMLockManager with the given number of locks.
18
// Due to the underlying implementation, the exact number of locks created may
19
// be greater than the number given here.
20
func NewSHMLockManager(path string, numLocks uint32) (Manager, error) {
21
	locks, err := shm.CreateSHMLock(path, numLocks)
22
	if err != nil {
23
		return nil, err
24
	}
25

26
	manager := new(SHMLockManager)
27
	manager.locks = locks
28

29
	return manager, nil
30
}
31

32
// OpenSHMLockManager opens an existing SHMLockManager with the given number of
33
// locks.
34
func OpenSHMLockManager(path string, numLocks uint32) (Manager, error) {
35
	locks, err := shm.OpenSHMLock(path, numLocks)
36
	if err != nil {
37
		return nil, err
38
	}
39

40
	manager := new(SHMLockManager)
41
	manager.locks = locks
42

43
	return manager, nil
44
}
45

46
// AllocateLock allocates a new lock from the manager.
47
func (m *SHMLockManager) AllocateLock() (Locker, error) {
48
	semIndex, err := m.locks.AllocateSemaphore()
49
	if err != nil {
50
		return nil, err
51
	}
52

53
	lock := new(SHMLock)
54
	lock.lockID = semIndex
55
	lock.manager = m
56

57
	return lock, nil
58
}
59

60
// AllocateAndRetrieveLock allocates the lock with the given ID and returns it.
61
// If the lock is already allocated, error.
62
func (m *SHMLockManager) AllocateAndRetrieveLock(id uint32) (Locker, error) {
63
	lock := new(SHMLock)
64
	lock.lockID = id
65
	lock.manager = m
66

67
	if id >= m.locks.GetMaxLocks() {
68
		return nil, fmt.Errorf("lock ID %d is too large - max lock size is %d: %w",
69
			id, m.locks.GetMaxLocks()-1, syscall.EINVAL)
70
	}
71

72
	if err := m.locks.AllocateGivenSemaphore(id); err != nil {
73
		return nil, err
74
	}
75

76
	return lock, nil
77
}
78

79
// RetrieveLock retrieves a lock from the manager given its ID.
80
func (m *SHMLockManager) RetrieveLock(id uint32) (Locker, error) {
81
	lock := new(SHMLock)
82
	lock.lockID = id
83
	lock.manager = m
84

85
	if id >= m.locks.GetMaxLocks() {
86
		return nil, fmt.Errorf("lock ID %d is too large - max lock size is %d: %w",
87
			id, m.locks.GetMaxLocks()-1, syscall.EINVAL)
88
	}
89

90
	return lock, nil
91
}
92

93
// FreeAllLocks frees all locks in the manager.
94
// This function is DANGEROUS. Please read the full comment in locks.go before
95
// trying to use it.
96
func (m *SHMLockManager) FreeAllLocks() error {
97
	return m.locks.DeallocateAllSemaphores()
98
}
99

100
// AvailableLocks returns the number of free locks in the manager.
101
func (m *SHMLockManager) AvailableLocks() (*uint32, error) {
102
	avail, err := m.locks.GetFreeLocks()
103
	if err != nil {
104
		return nil, err
105
	}
106

107
	return &avail, nil
108
}
109

110
func (m *SHMLockManager) LocksHeld() ([]uint32, error) {
111
	return m.locks.GetTakenLocks()
112
}
113

114
// SHMLock is an individual shared memory lock.
115
type SHMLock struct {
116
	lockID  uint32
117
	manager *SHMLockManager
118
}
119

120
// ID returns the ID of the lock.
121
func (l *SHMLock) ID() uint32 {
122
	return l.lockID
123
}
124

125
// Lock acquires the lock.
126
func (l *SHMLock) Lock() {
127
	if err := l.manager.locks.LockSemaphore(l.lockID); err != nil {
128
		panic(err.Error())
129
	}
130
}
131

132
// Unlock releases the lock.
133
func (l *SHMLock) Unlock() {
134
	if err := l.manager.locks.UnlockSemaphore(l.lockID); err != nil {
135
		panic(err.Error())
136
	}
137
}
138

139
// Free releases the lock, allowing it to be reused.
140
func (l *SHMLock) Free() error {
141
	return l.manager.locks.DeallocateSemaphore(l.lockID)
142
}
143

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.