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 | ||||
| #define UTIL_SHM_H | ||||
| 
 | ||||
| #include <stdbool.h> | ||||
| 
 | ||||
| int create_shm_file(void); | ||||
| int allocate_shm_file(size_t size); | ||||
| bool allocate_shm_file_pair(size_t size, int *rw_fd, int *ro_fd); | ||||
| 
 | ||||
| #endif | ||||
|  |  | |||
							
								
								
									
										44
									
								
								util/shm.c
								
								
								
								
							
							
						
						
									
										44
									
								
								util/shm.c
								
								
								
								
							|  | @ -8,6 +8,8 @@ | |||
| #include <wlr/config.h> | ||||
| #include "util/shm.h" | ||||
| 
 | ||||
| #define RANDNAME_PATTERN "/wlroots-XXXXXX" | ||||
| 
 | ||||
| static void randname(char *buf) { | ||||
| 	struct timespec 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; | ||||
| 	do { | ||||
| 		char name[] = "/wlroots-XXXXXX"; | ||||
| 		randname(name + strlen(name) - 6); | ||||
| 		randname(name + strlen(RANDNAME_PATTERN) - 6); | ||||
| 
 | ||||
| 		--retries; | ||||
| 		// CLOEXEC is guaranteed to be set by shm_open
 | ||||
| 		int fd = shm_open(name, O_RDWR | O_CREAT | O_EXCL, 0600); | ||||
| 		if (fd >= 0) { | ||||
| 			shm_unlink(name); | ||||
| 			return fd; | ||||
| 		} | ||||
| 	} while (retries > 0 && errno == EEXIST); | ||||
|  | @ -37,10 +37,12 @@ int create_shm_file(void) { | |||
| } | ||||
| 
 | ||||
| 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) { | ||||
| 		return -1; | ||||
| 	} | ||||
| 	shm_unlink(name); | ||||
| 
 | ||||
| 	int ret; | ||||
| 	do { | ||||
|  | @ -53,3 +55,35 @@ int allocate_shm_file(size_t size) { | |||
| 
 | ||||
| 	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