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 {