util/shm: add allocate_shm_file_pair
This function behaves like allocate_shm_file, except it also returns a read-only FD. This is useful to share the same segment of memory with many Wayland clients.
This commit is contained in:
		
							parent
							
								
									38cd1b4f4f
								
							
						
					
					
						commit
						55ca93469c
					
				|  | @ -1,7 +1,10 @@ | ||||||
| #ifndef UTIL_SHM_H | #ifndef UTIL_SHM_H | ||||||
| #define UTIL_SHM_H | #define UTIL_SHM_H | ||||||
| 
 | 
 | ||||||
|  | #include <stdbool.h> | ||||||
|  | 
 | ||||||
| int create_shm_file(void); | int create_shm_file(void); | ||||||
| int allocate_shm_file(size_t size); | int allocate_shm_file(size_t size); | ||||||
|  | bool allocate_shm_file_pair(size_t size, int *rw_fd, int *ro_fd); | ||||||
| 
 | 
 | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
							
								
								
									
										44
									
								
								util/shm.c
								
								
								
								
							
							
						
						
									
										44
									
								
								util/shm.c
								
								
								
								
							|  | @ -8,6 +8,8 @@ | ||||||
| #include <wlr/config.h> | #include <wlr/config.h> | ||||||
| #include "util/shm.h" | #include "util/shm.h" | ||||||
| 
 | 
 | ||||||
|  | #define RANDNAME_PATTERN "/wlroots-XXXXXX" | ||||||
|  | 
 | ||||||
| static void randname(char *buf) { | static void randname(char *buf) { | ||||||
| 	struct timespec ts; | 	struct timespec ts; | ||||||
| 	clock_gettime(CLOCK_REALTIME, &ts); | 	clock_gettime(CLOCK_REALTIME, &ts); | ||||||
|  | @ -18,17 +20,15 @@ static void randname(char *buf) { | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| int create_shm_file(void) { | static int excl_shm_open(char *name) { | ||||||
| 	int retries = 100; | 	int retries = 100; | ||||||
| 	do { | 	do { | ||||||
| 		char name[] = "/wlroots-XXXXXX"; | 		randname(name + strlen(RANDNAME_PATTERN) - 6); | ||||||
| 		randname(name + strlen(name) - 6); |  | ||||||
| 
 | 
 | ||||||
| 		--retries; | 		--retries; | ||||||
| 		// CLOEXEC is guaranteed to be set by shm_open
 | 		// CLOEXEC is guaranteed to be set by shm_open
 | ||||||
| 		int fd = shm_open(name, O_RDWR | O_CREAT | O_EXCL, 0600); | 		int fd = shm_open(name, O_RDWR | O_CREAT | O_EXCL, 0600); | ||||||
| 		if (fd >= 0) { | 		if (fd >= 0) { | ||||||
| 			shm_unlink(name); |  | ||||||
| 			return fd; | 			return fd; | ||||||
| 		} | 		} | ||||||
| 	} while (retries > 0 && errno == EEXIST); | 	} while (retries > 0 && errno == EEXIST); | ||||||
|  | @ -37,10 +37,12 @@ int create_shm_file(void) { | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| int allocate_shm_file(size_t size) { | int allocate_shm_file(size_t size) { | ||||||
| 	int fd = create_shm_file(); | 	char name[] = RANDNAME_PATTERN; | ||||||
|  | 	int fd = excl_shm_open(name); | ||||||
| 	if (fd < 0) { | 	if (fd < 0) { | ||||||
| 		return -1; | 		return -1; | ||||||
| 	} | 	} | ||||||
|  | 	shm_unlink(name); | ||||||
| 
 | 
 | ||||||
| 	int ret; | 	int ret; | ||||||
| 	do { | 	do { | ||||||
|  | @ -53,3 +55,35 @@ int allocate_shm_file(size_t size) { | ||||||
| 
 | 
 | ||||||
| 	return fd; | 	return fd; | ||||||
| } | } | ||||||
|  | 
 | ||||||
|  | bool allocate_shm_file_pair(size_t size, int *rw_fd_ptr, int *ro_fd_ptr) { | ||||||
|  | 	char name[] = RANDNAME_PATTERN; | ||||||
|  | 	int rw_fd = excl_shm_open(name); | ||||||
|  | 	if (rw_fd < 0) { | ||||||
|  | 		return false; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	// CLOEXEC is guaranteed to be set by shm_open
 | ||||||
|  | 	int ro_fd = shm_open(name, O_RDONLY, 0); | ||||||
|  | 	if (ro_fd < 0) { | ||||||
|  | 		shm_unlink(name); | ||||||
|  | 		close(rw_fd); | ||||||
|  | 		return false; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	shm_unlink(name); | ||||||
|  | 
 | ||||||
|  | 	int ret; | ||||||
|  | 	do { | ||||||
|  | 		ret = ftruncate(rw_fd, size); | ||||||
|  | 	} while (ret < 0 && errno == EINTR); | ||||||
|  | 	if (ret < 0) { | ||||||
|  | 		close(rw_fd); | ||||||
|  | 		close(ro_fd); | ||||||
|  | 		return false; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	*rw_fd_ptr = rw_fd; | ||||||
|  | 	*ro_fd_ptr = ro_fd; | ||||||
|  | 	return true; | ||||||
|  | } | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue