seat: Convert device list to linked list

This commit is contained in:
Kenny Levinsen 2020-08-03 02:12:47 +02:00
parent 4afe674e54
commit 9b7a12d90a
5 changed files with 33 additions and 32 deletions

View file

@ -6,6 +6,7 @@
#include <unistd.h> #include <unistd.h>
#include "connection.h" #include "connection.h"
#include "linked_list.h"
#include "list.h" #include "list.h"
struct server; struct server;
@ -23,7 +24,7 @@ struct client {
int seat_vt; int seat_vt;
bool pending_disable; bool pending_disable;
struct list devices; struct linked_list devices;
}; };
struct client *client_create(struct server *server, int client_fd); struct client *client_create(struct server *server, int client_fd);

View file

@ -1,11 +1,13 @@
#ifndef _SEATD_SEAT_H #ifndef _SEATD_SEAT_H
#define _SEATD_SEAT_H #define _SEATD_SEAT_H
#include "list.h"
#include <stdbool.h> #include <stdbool.h>
#include <stdint.h> #include <stdint.h>
#include <sys/types.h> #include <sys/types.h>
#include "linked_list.h"
#include "list.h"
struct client; struct client;
enum seat_device_type { enum seat_device_type {
@ -15,6 +17,7 @@ enum seat_device_type {
}; };
struct seat_device { struct seat_device {
struct linked_list link; // client::devices
int device_id; int device_id;
int fd; int fd;
int ref_cnt; int ref_cnt;

View file

@ -78,6 +78,7 @@ private_deps = []
server_files = [ server_files = [
'common/log.c', 'common/log.c',
'common/linked_list.c',
'common/list.c', 'common/list.c',
'common/terminal.c', 'common/terminal.c',
'common/connection.c', 'common/connection.c',

View file

@ -15,6 +15,7 @@
#endif #endif
#include "client.h" #include "client.h"
#include "linked_list.h"
#include "log.h" #include "log.h"
#include "poller.h" #include "poller.h"
#include "protocol.h" #include "protocol.h"
@ -67,7 +68,7 @@ struct client *client_create(struct server *server, int client_fd) {
client->pid = pid; client->pid = pid;
client->server = server; client->server = server;
client->connection.fd = client_fd; client->connection.fd = client_fd;
list_init(&client->devices); linked_list_init(&client->devices);
return client; return client;
} }
@ -102,8 +103,7 @@ void client_destroy(struct client *client) {
client->connection.fd = -1; client->connection.fd = -1;
} }
connection_close_fds(&client->connection); connection_close_fds(&client->connection);
assert(client->devices.length == 0); assert(linked_list_empty(&client->devices));
list_free(&client->devices);
free(client); free(client);
} }

View file

@ -95,9 +95,10 @@ int seat_remove_client(struct client *client) {
seat->next_client = NULL; seat->next_client = NULL;
} }
while (client->devices.length > 0) { while (!linked_list_empty(&client->devices)) {
struct seat_device *device = list_pop_back(&client->devices); struct seat_device *device = (struct seat_device *)client->devices.next;
seat_close_device(client, device); seat_close_device(client, device);
linked_list_remove(&device->link);
} }
if (seat->active_client == client) { if (seat->active_client == client) {
@ -115,8 +116,9 @@ struct seat_device *seat_find_device(struct client *client, int device_id) {
assert(client->seat); assert(client->seat);
assert(device_id != 0); assert(device_id != 0);
for (size_t idx = 0; idx < client->devices.length; idx++) { for (struct linked_list *elem = client->devices.next; elem != &client->devices;
struct seat_device *seat_device = client->devices.items[idx]; elem = elem->next) {
struct seat_device *seat_device = (struct seat_device *)elem;
if (seat_device->device_id == device_id) { if (seat_device->device_id == device_id) {
return seat_device; return seat_device;
} }
@ -159,8 +161,10 @@ struct seat_device *seat_open_device(struct client *client, const char *path) {
} }
int device_id = 1; int device_id = 1;
for (size_t idx = 0; idx < client->devices.length; idx++) { size_t device_count = 0;
struct seat_device *device = client->devices.items[idx]; for (struct linked_list *elem = client->devices.next; elem != &client->devices;
elem = elem->next) {
struct seat_device *device = (struct seat_device *)elem;
// If the device already exists, increase the ref count and // If the device already exists, increase the ref count and
// return it. // return it.
@ -173,9 +177,10 @@ struct seat_device *seat_open_device(struct client *client, const char *path) {
if (device->device_id >= device_id) { if (device->device_id >= device_id) {
device_id = device->device_id + 1; device_id = device->device_id + 1;
} }
device_count++;
} }
if (client->devices.length >= MAX_SEAT_DEVICES) { if (device_count >= MAX_SEAT_DEVICES) {
log_error("max seat devices exceeded"); log_error("max seat devices exceeded");
errno = EMFILE; errno = EMFILE;
return NULL; return NULL;
@ -225,7 +230,7 @@ struct seat_device *seat_open_device(struct client *client, const char *path) {
device->fd = fd; device->fd = fd;
device->device_id = device_id; device->device_id = device_id;
device->active = true; device->active = true;
list_add(&client->devices, device); linked_list_insert(&client->devices, &device->link);
return device; return device;
} }
@ -234,14 +239,6 @@ int seat_close_device(struct client *client, struct seat_device *seat_device) {
assert(client->seat); assert(client->seat);
assert(seat_device && seat_device->fd != -1); assert(seat_device && seat_device->fd != -1);
// Find the device in our list
size_t idx = list_find(&client->devices, seat_device);
if (idx == -1UL) {
log_error("seat device not registered by client");
errno = ENOENT;
return -1;
}
log_debugf("seat: %p, client: %p, path: '%s', device_id: %d", (void *)client->seat, log_debugf("seat: %p, client: %p, path: '%s', device_id: %d", (void *)client->seat,
(void *)client, seat_device->path, seat_device->device_id); (void *)client, seat_device->path, seat_device->device_id);
@ -252,7 +249,7 @@ int seat_close_device(struct client *client, struct seat_device *seat_device) {
} }
// The ref count hit zero, so destroy the device // The ref count hit zero, so destroy the device
list_del(&client->devices, idx); linked_list_remove(&seat_device->link);
if (seat_device->active && seat_device->fd != -1) { if (seat_device->active && seat_device->fd != -1) {
switch (seat_device->type) { switch (seat_device->type) {
case SEAT_DEVICE_TYPE_DRM: case SEAT_DEVICE_TYPE_DRM:
@ -372,15 +369,14 @@ int seat_open_client(struct seat *seat, struct client *client) {
seat->curttyfd = ttyfd; seat->curttyfd = ttyfd;
} }
for (size_t idx = 0; idx < client->devices.length; idx++) { for (struct linked_list *elem = client->devices.next; elem != &client->devices;
struct seat_device *device = client->devices.items[idx]; elem = elem->next) {
struct seat_device *device = (struct seat_device *)elem;
if (seat_activate_device(client, device) == -1) { if (seat_activate_device(client, device) == -1) {
log_errorf("unable to activate '%s': %s", device->path, strerror(errno)); log_errorf("unable to activate '%s': %s", device->path, strerror(errno));
} }
} }
log_debugf("activated %zd devices", client->devices.length);
seat->active_client = client; seat->active_client = client;
if (client_send_enable_seat(client) == -1) { if (client_send_enable_seat(client) == -1) {
seat_remove_client(client); seat_remove_client(client);
@ -403,11 +399,12 @@ int seat_close_client(struct client *client) {
return -1; return -1;
} }
while (client->devices.length > 0) { while (!linked_list_empty(&client->devices)) {
struct seat_device *device = list_pop_back(&client->devices); struct seat_device *device = (struct seat_device *)client->devices.next;
if (seat_close_device(client, device) == -1) { if (seat_close_device(client, device) == -1) {
log_errorf("unable to close '%s': %s", device->path, strerror(errno)); log_errorf("unable to close '%s': %s", device->path, strerror(errno));
} }
linked_list_remove(&device->link);
} }
client->pending_disable = false; client->pending_disable = false;
@ -433,15 +430,14 @@ static int seat_disable_client(struct client *client) {
// The reason we cannot just close them is that certain device fds, such // The reason we cannot just close them is that certain device fds, such
// as for DRM, must maintain the exact same file description for their // as for DRM, must maintain the exact same file description for their
// contexts to remain valid. // contexts to remain valid.
for (size_t idx = 0; idx < client->devices.length; idx++) { for (struct linked_list *elem = client->devices.next; elem != &client->devices;
struct seat_device *device = client->devices.items[idx]; elem = elem->next) {
struct seat_device *device = (struct seat_device *)elem;
if (seat_deactivate_device(client, device) == -1) { if (seat_deactivate_device(client, device) == -1) {
log_errorf("unable to deactivate '%s': %s", device->path, strerror(errno)); log_errorf("unable to deactivate '%s': %s", device->path, strerror(errno));
} }
} }
log_debugf("deactivated %zd devices", client->devices.length);
client->pending_disable = true; client->pending_disable = true;
if (client_send_disable_seat(seat->active_client) == -1) { if (client_send_disable_seat(seat->active_client) == -1) {
seat_remove_client(client); seat_remove_client(client);