diff options
author | Andrew Lewycky <Andrew.Lewycky@amd.com> | 2014-10-13 11:30:18 +0300 |
---|---|---|
committer | Oded Gabbay <oded.gabbay@gmail.com> | 2015-05-05 12:26:59 +0300 |
commit | 201e9ff0907484f9b1089a36971f57e6aa8fbcf1 (patch) | |
tree | 3acd2b7a725266e11c1aec57a2e19745af2738fb | |
parent | 7b889dde713fcf7b4e4b3c9bbe6f58ea370b8579 (diff) |
Add HSA Signals module
Signed-off-by: Andrew Lewycky <Andrew.Lewycky@amd.com>
Signed-off-by: Oded Gabbay <oded.gabbay@amd.com>
-rw-r--r-- | src/events.c | 162 |
1 files changed, 132 insertions, 30 deletions
diff --git a/src/events.c b/src/events.c index cb07116..be58253 100644 --- a/src/events.c +++ b/src/events.c @@ -25,9 +25,20 @@ #include "libhsakmt.h" #include <stdlib.h> +#include <string.h> #include <time.h> #include <errno.h> #include <unistd.h> +#include <sys/mman.h> +#include "linux/kfd_ioctl.h" + +static HSAuint64 *events_page = NULL; + +static bool IsSystemEventType(HSA_EVENTTYPE type) +{ + // Debug events behave as signal events. + return (type != HSA_EVENTTYPE_SIGNAL && type != HSA_EVENTTYPE_DEBUG_EVENT); +} HSAKMT_STATUS HSAKMTAPI @@ -51,6 +62,45 @@ hsaKmtCreateEvent( return HSAKMT_STATUS_ERROR; } + memset(e, 0, sizeof(*e)); + + struct kfd_ioctl_create_event_args args; + memset(&args, 0, sizeof(args)); + + args.event_type = EventDesc->EventType; + args.auto_reset = !ManualReset; + + if (kmtIoctl(kfd_fd, AMDKFD_IOC_CREATE_EVENT, &args) != 0) { + free(e); + *Event = NULL; + return HSAKMT_STATUS_ERROR; + } + + if (events_page == NULL && args.event_page_offset > 0) { + events_page = mmap(NULL, 4096, PROT_WRITE | PROT_READ, + MAP_SHARED, kfd_fd, args.event_page_offset); + if (events_page == NULL) { + hsaKmtDestroyEvent(e); + return HSAKMT_STATUS_ERROR; + } + } + + if (args.event_page_offset > 0 && args.event_slot_index < KFD_SIGNAL_EVENT_LIMIT) + e->EventData.HWData2 = (HSAuint64)&events_page[args.event_slot_index]; + + e->EventId = args.event_id; + e->EventData.HWData1 = args.event_id; + + e->EventData.HWData3 = args.event_trigger_data; + + if (IsSignaled && !IsSystemEventType(e->EventData.EventType)) { + struct kfd_ioctl_set_event_args set_args; + memset(&set_args, 0, sizeof(set_args)); + set_args.event_id = args.event_id; + + kmtIoctl(kfd_fd, AMDKFD_IOC_SET_EVENT, &set_args); + } + *Event = e; return HSAKMT_STATUS_SUCCESS; @@ -64,6 +114,18 @@ hsaKmtDestroyEvent( { CHECK_KFD_OPEN(); + if (!Event) + return HSAKMT_STATUS_INVALID_HANDLE; + + struct kfd_ioctl_destroy_event_args args; + memset(&args, 0, sizeof(args)); + + args.event_id = Event->EventId; + + if (kmtIoctl(kfd_fd, AMDKFD_IOC_DESTROY_EVENT, &args) != 0) { + return HSAKMT_STATUS_ERROR; + } + free(Event); return HSAKMT_STATUS_SUCCESS; @@ -76,6 +138,22 @@ hsaKmtSetEvent( ) { CHECK_KFD_OPEN(); + + if (!Event) + return HSAKMT_STATUS_INVALID_HANDLE; + + /* Although the spec is doesn't say, don't allow system-defined events to be signaled. */ + if (IsSystemEventType(Event->EventData.EventType)) + return HSAKMT_STATUS_ERROR; + + struct kfd_ioctl_set_event_args args; + memset(&args, 0, sizeof(args)); + + args.event_id = Event->EventId; + + if (kmtIoctl(kfd_fd, AMDKFD_IOC_SET_EVENT, &args) == -1) + return HSAKMT_STATUS_ERROR; + return HSAKMT_STATUS_SUCCESS; } @@ -86,6 +164,22 @@ hsaKmtResetEvent( ) { CHECK_KFD_OPEN(); + + if (!Event) + return HSAKMT_STATUS_INVALID_HANDLE; + + /* Although the spec is doesn't say, don't allow system-defined events to be signaled. */ + if (IsSystemEventType(Event->EventData.EventType)) + return HSAKMT_STATUS_ERROR; + + struct kfd_ioctl_reset_event_args args; + memset(&args, 0, sizeof(args)); + + args.event_id = Event->EventId; + + if (kmtIoctl(kfd_fd, AMDKFD_IOC_RESET_EVENT, &args) == -1) + return HSAKMT_STATUS_ERROR; + return HSAKMT_STATUS_SUCCESS; } @@ -96,6 +190,10 @@ hsaKmtQueryEventState( ) { CHECK_KFD_OPEN(); + + if (!Event) + return HSAKMT_STATUS_INVALID_HANDLE; + return HSAKMT_STATUS_SUCCESS; } @@ -106,36 +204,10 @@ hsaKmtWaitOnEvent( HSAuint32 Milliseconds //IN ) { - CHECK_KFD_OPEN(); - - if (Milliseconds == HSA_EVENTTIMEOUT_INFINITE) - { - while (1) { pause(); } - } - else if (Milliseconds != HSA_EVENTTIMEOUT_IMMEDIATE) - { - struct timespec req; - - req.tv_sec = Milliseconds / 1000; - req.tv_nsec = (long)(Milliseconds % 1000) * 1000000; - - while (1) - { - struct timespec rem; - - int err = nanosleep(&req, &rem); - if (err == -1 && errno == EINTR) - { - req = rem; - } - else - { - break; // success or other error - } - } - } + if (!Event) + return HSAKMT_STATUS_INVALID_HANDLE; - return HSAKMT_STATUS_WAIT_TIMEOUT; + return hsaKmtWaitOnMultipleEvents(&Event, 1, true, Milliseconds); } HSAKMT_STATUS @@ -149,5 +221,35 @@ hsaKmtWaitOnMultipleEvents( { CHECK_KFD_OPEN(); - return hsaKmtWaitOnEvent(NULL, Milliseconds); + if (!Events) + return HSAKMT_STATUS_INVALID_HANDLE; + + uint32_t *event_ids = malloc(NumEvents * sizeof(uint32_t)); + for (HSAuint32 i = 0; i < NumEvents; i++) { + event_ids[i] = Events[i]->EventId; + } + + struct kfd_ioctl_wait_events_args args; + memset(&args, 0, sizeof(args)); + + args.wait_for_all = WaitOnAll; + args.timeout = Milliseconds; + args.num_events = NumEvents; + args.events_ptr = (uint64_t)(uintptr_t)event_ids; + + HSAKMT_STATUS result; + + if (kmtIoctl(kfd_fd, AMDKFD_IOC_WAIT_EVENTS, &args) == -1) { + result = HSAKMT_STATUS_ERROR; + } + else if (args.wait_result == KFD_IOC_WAIT_RESULT_TIMEOUT) { + result = HSAKMT_STATUS_WAIT_TIMEOUT; + } + else { + result = HSAKMT_STATUS_SUCCESS; + } + + free(event_ids); + + return result; } |