worked on the acpi namespace dumper: I kept the recursive implementation of the function, but I had to use a different thread, then, to read the data, without smashing the buffer passed by read(). It still doesnt' work correctly 100% (because I obviously made some stupid mistake, please review), but at least 'cat /dev/acpi/namespace' doesn't KDL anymore, and it even shows something.

git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@28034 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Stefano Ceccherini
2008-10-13 13:55:53 +00:00
parent 25174582be
commit 06679066a3
@@ -11,16 +11,22 @@
#include "acpi_priv.h"
#include <util/ring_buffer.h>
typedef struct acpi_ns_device_info {
device_node *node;
acpi_root_info *acpi;
void *acpi_cookie;
thread_id thread;
struct ring_buffer *buffer;
sem_id write_sem;
sem_id sync_sem;
} acpi_ns_device_info;
static void
dump_acpi_namespace(acpi_ns_device_info *device, char *root, void *buf, size_t* num_bytes, int indenting)
dump_acpi_namespace(acpi_ns_device_info *device, char *root, int indenting)
{
char result[255];
char output[255];
@@ -29,7 +35,7 @@ dump_acpi_namespace(acpi_ns_device_info *device, char *root, void *buf, size_t*
int i, depth;
uint32 type;
void *counter = NULL;
size_t written = 0;
hid[8] = '\0';
tabs[0] = '\0';
for (i = 0; i < indenting; i++) {
@@ -38,7 +44,7 @@ dump_acpi_namespace(acpi_ns_device_info *device, char *root, void *buf, size_t*
sprintf(tabs, "%s|--- ", tabs);
depth = sizeof(char) * 5 * indenting + sizeof(char); // index into result where the device name will be.
dprintf("acpi_ns_dump: recursing from %s, depth %d\n", root, depth);
//dprintf("acpi_ns_dump: recursing from %s, depth %d\n", root, depth);
while (device->acpi->get_next_entry(ACPI_TYPE_ANY, root, result, 255, &counter) == B_OK) {
type = device->acpi->get_object_type(result);
sprintf(output, "%s%s", tabs, result + depth);
@@ -89,14 +95,30 @@ dump_acpi_namespace(acpi_ns_device_info *device, char *root, void *buf, size_t*
sprintf(output, "%s BUFFER_FIELD", output);
break;
}
// TODO: This is obviously broken!
// We should respect "*num_bytes", otherwise
// we could have a buffer overflow. See ticket #2786
sprintf((buf + *num_bytes), "%s", output);
*num_bytes += strlen(output);
dump_acpi_namespace(device, result, buf, num_bytes, indenting + 1);
written = 0;
if (acquire_sem(device->sync_sem) == B_OK) {
//dprintf("writing %ld bytes to the buffer.\n", strlen(output));
written = ring_buffer_write(device->buffer, output, strlen(output));
//dprintf("written %ld bytes\n", written);
release_sem(device->sync_sem);
}
if (written > 0)
release_sem_etc(device->write_sem, 1, 0);
dump_acpi_namespace(device, result, indenting + 1);
}
// dprintf("dump_acpi_namespace() returns\n");
}
static int32
acpi_namespace_dump(void *arg)
{
acpi_ns_device_info *device = (acpi_ns_device_info*)(arg);
dump_acpi_namespace(device, "\\", 0);
release_sem(device->write_sem);
return 0;
}
@@ -108,9 +130,31 @@ static status_t
acpi_namespace_open(void *_cookie, const char* path, int flags, void** cookie)
{
acpi_ns_device_info *device = (acpi_ns_device_info *)_cookie;
dprintf("\nacpi_ns_dump: device_open\n");
*cookie = device;
device->buffer = create_ring_buffer(2048);
device->write_sem = create_sem(0, "sem");
if (device->write_sem < 0)
return device->write_sem;
device->sync_sem = create_sem(1, "sync sem");
if (device->sync_sem < 0) {
delete_sem(device->write_sem);
return device->sync_sem;
}
device->thread = spawn_kernel_thread(acpi_namespace_dump, "acpi dumper",
B_NORMAL_PRIORITY, device);
if (device->thread < 0) {
delete_sem(device->write_sem);
delete_sem(device->sync_sem);
return device->thread;
}
resume_thread(device->thread);
return B_OK;
}
@@ -122,22 +166,31 @@ static status_t
acpi_namespace_read(void *_cookie, off_t position, void *buf, size_t* num_bytes)
{
acpi_ns_device_info *device = (acpi_ns_device_info *)_cookie;
size_t bytes = 0;
dprintf("acpi_namespace_read(cookie: %p, position: %ld, buffer: %p, size: %ld)\n",
_cookie, position, buf, *num_bytes);
if (position == 0) { // First read
dump_acpi_namespace(device, "\\", buf, &bytes, 0);
if (bytes <= *num_bytes) {
*num_bytes = bytes;
dprintf("acpi_ns_dump: read %lu bytes\n", *num_bytes);
} else {
*num_bytes = 0;
return B_IO_ERROR;
size_t bytesRead = -1;
size_t bytesToRead = 0;
status_t status;
dprintf("acpi_namespace_read(cookie: %p, position: %ld, buffer: %p, size: %ld)\n",
_cookie, position, buf, *num_bytes);
status = acquire_sem_etc(device->write_sem, 1, 0, 0);
if (status == B_OK) {
if (acquire_sem(device->sync_sem) == B_OK) {
bytesToRead = ring_buffer_readable(device->buffer);
bytesRead = ring_buffer_read(device->buffer, buf, bytesToRead);
release_sem(device->sync_sem);
}
} else {
}
dprintf("semaphore acquired: %s\n", strerror(status));
if (bytesRead < 0) {
*num_bytes = 0;
dprintf("returning %s\n", strerror(bytesRead));
return bytesRead;
}
*num_bytes = bytesRead;
dprintf("%ld bytes read\n", bytesRead);
return B_OK;
}
@@ -174,7 +227,15 @@ acpi_namespace_control(void* cookie, uint32 op, void* arg, size_t len)
static status_t
acpi_namespace_close(void* cookie)
{
status_t status;
dprintf("acpi_ns_dump: device_close\n");
acpi_ns_device_info *device = (acpi_ns_device_info *)cookie;
delete_sem(device->write_sem);
delete_sem(device->sync_sem);
wait_for_thread(device->thread, &status);
delete_ring_buffer(device->buffer);
return B_OK;
}
@@ -187,7 +248,7 @@ static status_t
acpi_namespace_free(void* cookie)
{
dprintf("acpi_ns_dump: device_free\n");
return B_OK;
}
@@ -213,7 +274,7 @@ acpi_namespace_init_device(void *_cookie, void **cookie)
return err;
}
*cookie = device;
*cookie = device;
return B_OK;
}