Mercurial > repos > blastem
comparison util.c @ 2703:829205a9647a default tip
Pump events and allow debug window interaction while paused in CPU debugger on Windows
author | Michael Pavone <pavone@retrodev.com> |
---|---|
date | Fri, 04 Jul 2025 21:24:15 -0700 |
parents | 143cb5762ec9 |
children |
comparison
equal
deleted
inserted
replaced
2702:0a6d644c47aa | 2703:829205a9647a |
---|---|
755 int socket_error_is_wouldblock(void) | 755 int socket_error_is_wouldblock(void) |
756 { | 756 { |
757 return WSAGetLastError() == WSAEWOULDBLOCK; | 757 return WSAGetLastError() == WSAEWOULDBLOCK; |
758 } | 758 } |
759 | 759 |
760 typedef struct { | |
761 HANDLE request_event; | |
762 HANDLE reply_event; | |
763 CRITICAL_SECTION lock; | |
764 FILE *f; | |
765 char *dst; | |
766 size_t size; | |
767 } stdio_timeout_state; | |
768 | |
769 static DWORD WINAPI stdio_timeout_thread(LPVOID param) | |
770 { | |
771 stdio_timeout_state *state = param; | |
772 EnterCriticalSection(&state->lock); | |
773 for(;;) | |
774 { | |
775 while (!state->f) | |
776 { | |
777 LeaveCriticalSection(&state->lock); | |
778 WaitForSingleObject(state->request_event, INFINITE); | |
779 EnterCriticalSection(&state->lock); | |
780 } | |
781 char *dst = state->dst; | |
782 size_t size = state->size; | |
783 FILE *f = state->f; | |
784 LeaveCriticalSection(&state->lock); | |
785 dst = fgets(dst, size, f); | |
786 EnterCriticalSection(&state->lock); | |
787 state->dst = dst; | |
788 state->f = NULL; | |
789 SetEvent(&state->reply_event); | |
790 } | |
791 LeaveCriticalSection(&state->lock); | |
792 | |
793 return 0; | |
794 } | |
795 | |
796 char *fgets_timeout(char *dst, size_t size, FILE *f, uint64_t timeout_usec, void (*timeout_cb)(void)) | |
797 { | |
798 static HANDLE workerThread; | |
799 static stdio_timeout_state state; | |
800 if (!workerThread) { | |
801 InitializeCriticalSection(&state.lock); | |
802 state.request_event = CreateEventA(NULL, FALSE, FALSE, NULL); | |
803 state.reply_event = CreateEventA(NULL, FALSE, FALSE, NULL); | |
804 workerThread = CreateThread(NULL, 64 * 1024, stdio_timeout_thread, &state, 0, NULL); | |
805 } | |
806 EnterCriticalSection(&state.lock); | |
807 state.f = f; | |
808 state.dst = dst; | |
809 state.size = size; | |
810 SetEvent(state.request_event); | |
811 while (state.f) | |
812 { | |
813 LeaveCriticalSection(&state.lock); | |
814 WaitForSingleObject(state.reply_event, timeout_usec / 1000); | |
815 EnterCriticalSection(&state.lock); | |
816 if (state.f) { | |
817 timeout_cb(); | |
818 } | |
819 } | |
820 LeaveCriticalSection(&state.lock); | |
821 return state.dst; | |
822 } | |
823 | |
760 #else | 824 #else |
761 #include <fcntl.h> | 825 #include <fcntl.h> |
762 #include <signal.h> | 826 #include <signal.h> |
763 | 827 |
764 void socket_init(void) | 828 void socket_init(void) |
862 } | 926 } |
863 #endif | 927 #endif |
864 } | 928 } |
865 return exe_dir; | 929 return exe_dir; |
866 } | 930 } |
931 | |
932 char *fgets_timeout(char *dst, size_t size, FILE *f, uint64_t timeout_usec, void (*timeout_cb)(void)) | |
933 { | |
934 int wait = 1; | |
935 fd_set read_fds; | |
936 FD_ZERO(&read_fds); | |
937 struct timeval timeout; | |
938 do { | |
939 timeout.tv_sec = timeout_usec / 1000000; | |
940 timeout.tv_usec = timeout_usec % 1000000; | |
941 FD_SET(fileno(stdin), &read_fds); | |
942 if(select(fileno(stdin) + 1, &read_fds, NULL, NULL, &timeout) >= 1) { | |
943 wait = 0; | |
944 } else { | |
945 timeout_cb(); | |
946 } | |
947 } while (wait); | |
948 return fgets(dst, size, f); | |
949 } | |
950 | |
867 #include <dirent.h> | 951 #include <dirent.h> |
868 | 952 |
869 #ifdef __ANDROID__ | 953 #ifdef __ANDROID__ |
870 static dir_entry *jdir_list_helper(JNIEnv *env, jmethodID meth, char *path, size_t *numret) | 954 static dir_entry *jdir_list_helper(JNIEnv *env, jmethodID meth, char *path, size_t *numret) |
871 { | 955 { |