ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/SheepShaver/src/Unix/main_unix.cpp
(Generate patch)

Comparing SheepShaver/src/Unix/main_unix.cpp (file contents):
Revision 1.2 by cebix, 2002-02-21T15:12:12Z vs.
Revision 1.15 by gbeauche, 2003-12-04T17:26:37Z

# Line 107 | Line 107
107   #include "macos_util.h"
108   #include "rom_patches.h"
109   #include "user_strings.h"
110 + #include "vm_alloc.h"
111 + #include "sigsegv.h"
112 + #include "thunks.h"
113  
114   #define DEBUG 0
115   #include "debug.h"
# Line 143 | Line 146
146   const char ROM_FILE_NAME[] = "ROM";
147   const char ROM_FILE_NAME2[] = "Mac OS ROM";
148  
149 < const uint32 ROM_AREA_SIZE = 0x500000;          // Size of ROM area
147 < const uint32 ROM_END = ROM_BASE + ROM_SIZE;     // End of ROM
148 <
149 < const uint32 KERNEL_DATA_BASE = 0x68ffe000;     // Address of Kernel Data
150 < const uint32 KERNEL_DATA2_BASE = 0x5fffe000;    // Alternate address of Kernel Data
151 < const uint32 KERNEL_AREA_SIZE = 0x2000;         // Size of Kernel Data area
152 <
149 > const uintptr RAM_BASE = 0x20000000;            // Base address of RAM
150   const uint32 SIG_STACK_SIZE = 0x10000;          // Size of signal stack
151  
152  
156 // 68k Emulator Data
157 struct EmulatorData {
158        uint32  v[0x400];      
159 };
160
161
162 // Kernel Data
163 struct KernelData {
164        uint32  v[0x400];
165        EmulatorData ed;
166 };
167
168
153   #if !EMULATED_PPC
154   // Structure in which registers are saved in a signal handler;
155   // sigcontext->regs points to it
# Line 197 | Line 181 | int64 BusClockSpeed;   // Bus clock speed
181  
182  
183   // Global variables
184 < static char *x_display_name = NULL;                     // X11 display name
184 > char *x_display_name = NULL;                            // X11 display name
185   Display *x_display = NULL;                                      // X11 display handle
186  
187   static int zero_fd = 0;                                         // FD of /dev/zero
# Line 205 | Line 189 | static bool lm_area_mapped = false;                    //
189   static int kernel_area = -1;                            // SHM ID of Kernel Data area
190   static bool rom_area_mapped = false;            // Flag: Mac ROM mmap()ped
191   static bool ram_area_mapped = false;            // Flag: Mac RAM mmap()ped
208 static void *mmap_RAMBase = NULL;                       // Base address of mmap()ed RAM area
192   static KernelData *kernel_data;                         // Pointer to Kernel Data
193   static EmulatorData *emulator_data;
194  
# Line 220 | Line 203 | static pthread_t emul_thread;                          // MacO
203   static bool ready_for_signals = false;          // Handler installed, signals can be sent
204   static int64 num_segv = 0;                                      // Number of handled SEGV signals
205  
223 #if !EMULATED_PPC
206   static struct sigaction sigusr2_action;         // Interrupt signal (of emulator thread)
207 + #if !EMULATED_PPC
208   static struct sigaction sigsegv_action;         // Data access exception signal (of emulator thread)
209   static struct sigaction sigill_action;          // Illegal instruction signal (of emulator thread)
210   static void *sig_stack = NULL;                          // Stack for signal handlers
# Line 230 | Line 213 | static bool emul_thread_fatal = false;
213   static sigregs sigsegv_regs;                            // Register dump when crashed
214   #endif
215  
216 + uintptr SheepMem::base = 0x60000000;            // Address of SheepShaver data
217 + uintptr SheepMem::top = 0;                                      // Top of SheepShaver data (stack like storage)
218 +
219  
220   // Prototypes
221   static void Quit(void);
222   static void *emul_func(void *arg);
223   static void *nvram_func(void *arg);
224   static void *tick_func(void *arg);
225 < #if !EMULATED_PPC
225 > #if EMULATED_PPC
226 > static void sigusr2_handler(int sig);
227 > extern void emul_ppc(uint32 start);
228 > extern void init_emul_ppc(void);
229 > extern void exit_emul_ppc(void);
230 > #else
231   static void sigusr2_handler(int sig, sigcontext_struct *sc);
232   static void sigsegv_handler(int sig, sigcontext_struct *sc);
233   static void sigill_handler(int sig, sigcontext_struct *sc);
# Line 244 | Line 235 | static void sigill_handler(int sig, sigc
235  
236  
237   // From asm_linux.S
238 < #if EMULATED_PPC
248 < extern int atomic_add(int *var, int v);
249 < extern int atomic_and(int *var, int v);
250 < extern int atomic_or(int *var, int v);
251 < #else
238 > #if !EMULATED_PPC
239   extern "C" void *get_toc(void);
240   extern "C" void *get_sp(void);
241   extern "C" void flush_icache_range(void *start, void *end);
# Line 263 | Line 250 | extern void paranoia_check(void);
250   #endif
251  
252  
253 < // Decode LZSS data
254 < static void decode_lzss(const uint8 *src, uint8 *dest, int size)
253 > #if EMULATED_PPC
254 > /*
255 > *  Atomic operations
256 > */
257 >
258 > #if HAVE_SPINLOCKS
259 > static spinlock_t atomic_ops_lock = SPIN_LOCK_UNLOCKED;
260 > #else
261 > #define spin_lock(LOCK)
262 > #define spin_unlock(LOCK)
263 > #endif
264 >
265 > int atomic_add(int *var, int v)
266 > {
267 >        spin_lock(&atomic_ops_lock);
268 >        int ret = *var;
269 >        *var += v;
270 >        spin_unlock(&atomic_ops_lock);
271 >        return ret;
272 > }
273 >
274 > int atomic_and(int *var, int v)
275   {
276 <        char dict[0x1000];
277 <        int run_mask = 0, dict_idx = 0xfee;
278 <        for (;;) {
279 <                if (run_mask < 0x100) {
280 <                        // Start new run
274 <                        if (--size < 0)
275 <                                break;
276 <                        run_mask = *src++ | 0xff00;
277 <                }
278 <                bool bit = run_mask & 1;
279 <                run_mask >>= 1;
280 <                if (bit) {
281 <                        // Verbatim copy
282 <                        if (--size < 0)
283 <                                break;
284 <                        int c = *src++;
285 <                        dict[dict_idx++] = c;
286 <                        *dest++ = c;
287 <                        dict_idx &= 0xfff;
288 <                } else {
289 <                        // Copy from dictionary
290 <                        if (--size < 0)
291 <                                break;
292 <                        int idx = *src++;
293 <                        if (--size < 0)
294 <                                break;
295 <                        int cnt = *src++;
296 <                        idx |= (cnt << 4) & 0xf00;
297 <                        cnt = (cnt & 0x0f) + 3;
298 <                        while (cnt--) {
299 <                                char c = dict[idx++];
300 <                                dict[dict_idx++] = c;
301 <                                *dest++ = c;
302 <                                idx &= 0xfff;
303 <                                dict_idx &= 0xfff;
304 <                        }
305 <                }
306 <        }
276 >        spin_lock(&atomic_ops_lock);
277 >        int ret = *var;
278 >        *var &= v;
279 >        spin_unlock(&atomic_ops_lock);
280 >        return ret;
281   }
282  
283 + int atomic_or(int *var, int v)
284 + {
285 +        spin_lock(&atomic_ops_lock);
286 +        int ret = *var;
287 +        *var |= v;
288 +        spin_unlock(&atomic_ops_lock);
289 +        return ret;
290 + }
291 + #endif
292 +
293  
294   /*
295   *  Main program
# Line 325 | Line 309 | int main(int argc, char **argv)
309          char str[256];
310          uint32 *boot_globs;
311          int16 i16;
328        int drive, driver;
312          int rom_fd;
313          FILE *proc_file;
314          const char *rom_path;
# Line 335 | Line 318 | int main(int argc, char **argv)
318  
319          // Initialize variables
320          RAMBase = 0;
338        mmap_RAMBase = NULL;
321          tzset();
322  
323          // Print some info
# Line 464 | Line 446 | int main(int argc, char **argv)
446          }
447  
448          // Create Low Memory area (0x0000..0x3000)
449 <        if (mmap((char *)0x0000, 0x3000, PROT_READ | PROT_WRITE, MAP_FIXED | MAP_PRIVATE, zero_fd, 0) == (void *)-1) {
449 >        if (vm_acquire_fixed((char *)0, 0x3000) < 0) {
450                  sprintf(str, GetString(STR_LOW_MEM_MMAP_ERR), strerror(errno));
451                  ErrorAlert(str);
452                  goto quit;
# Line 488 | Line 470 | int main(int argc, char **argv)
470                  ErrorAlert(str);
471                  goto quit;
472          }
473 <        kernel_data = (KernelData *)0x68ffe000;
473 >        kernel_data = (KernelData *)KERNEL_DATA_BASE;
474          emulator_data = &kernel_data->ed;
475 <        KernelDataAddr = (uint32)kernel_data;
475 >        KernelDataAddr = KERNEL_DATA_BASE;
476          D(bug("Kernel Data at %p, Emulator Data at %p\n", kernel_data, emulator_data));
477  
478 +        // Create area for SheepShaver data
479 +        if (!SheepMem::Init()) {
480 +                sprintf(str, GetString(STR_SHEEP_MEM_MMAP_ERR), strerror(errno));
481 +                ErrorAlert(str);
482 +                goto quit;
483 +        }
484 +
485          // Create area for Mac ROM
486 <        if (mmap((char *)ROM_BASE, ROM_AREA_SIZE, PROT_EXEC | PROT_READ | PROT_WRITE, MAP_FIXED | MAP_PRIVATE, zero_fd, 0) == (void *)-1) {
486 >        if (vm_acquire_fixed((char *)ROM_BASE, ROM_AREA_SIZE) < 0) {
487                  sprintf(str, GetString(STR_ROM_MMAP_ERR), strerror(errno));
488                  ErrorAlert(str);
489                  goto quit;
490          }
491 + #if !EMULATED_PPC || defined(__powerpc__)
492 +        if (vm_protect((char *)ROM_BASE, ROM_AREA_SIZE, VM_PAGE_READ | VM_PAGE_WRITE | VM_PAGE_EXECUTE) < 0) {
493 +                sprintf(str, GetString(STR_ROM_MMAP_ERR), strerror(errno));
494 +                ErrorAlert(str);
495 +                goto quit;
496 +        }
497 + #endif
498          rom_area_mapped = true;
499          D(bug("ROM area at %08x\n", ROM_BASE));
500  
# Line 509 | Line 505 | int main(int argc, char **argv)
505                  RAMSize = 8*1024*1024;
506          }
507  
508 <        mmap_RAMBase = mmap((void *)0x20000000, RAMSize, PROT_EXEC | PROT_READ | PROT_WRITE, MAP_FIXED | MAP_PRIVATE, zero_fd, 0);
509 <        if (mmap_RAMBase == (void *)-1) {
508 >        if (vm_acquire_fixed((char *)RAM_BASE, RAMSize) < 0) {
509 >                sprintf(str, GetString(STR_RAM_MMAP_ERR), strerror(errno));
510 >                ErrorAlert(str);
511 >                goto quit;
512 >        }
513 > #if !EMULATED_PPC
514 >        if (vm_protect((char *)RAM_BASE, RAMSize, VM_PAGE_READ | VM_PAGE_WRITE | VM_PAGE_EXECUTE) < 0) {
515                  sprintf(str, GetString(STR_RAM_MMAP_ERR), strerror(errno));
516                  ErrorAlert(str);
517                  goto quit;
518          }
519 <        RAMBase = (uint32)mmap_RAMBase;
519 > #endif
520 >        RAMBase = RAM_BASE;
521          ram_area_mapped = true;
522          D(bug("RAM area at %08x\n", RAMBase));
523  
# Line 540 | Line 542 | int main(int argc, char **argv)
542          rom_tmp = new uint8[ROM_SIZE];
543          actual = read(rom_fd, (void *)rom_tmp, ROM_SIZE);
544          close(rom_fd);
545 <        if (actual == ROM_SIZE) {
546 <                // Plain ROM image
547 <                memcpy((void *)ROM_BASE, rom_tmp, ROM_SIZE);
548 <                delete[] rom_tmp;
547 <        } else {
548 <                if (strncmp((char *)rom_tmp, "<CHRP-BOOT>", 11) == 0) {
549 <                        // CHRP compressed ROM image
550 <                        D(bug("CHRP ROM image\n"));
551 <                        uint32 lzss_offset, lzss_size;
552 <
553 <                        char *s = strstr((char *)rom_tmp, "constant lzss-offset");
554 <                        if (s == NULL) {
555 <                                ErrorAlert(GetString(STR_ROM_SIZE_ERR));
556 <                                goto quit;
557 <                        }
558 <                        s -= 7;
559 <                        if (sscanf(s, "%06x", &lzss_offset) != 1) {
560 <                                ErrorAlert(GetString(STR_ROM_SIZE_ERR));
561 <                                goto quit;
562 <                        }
563 <                        s = strstr((char *)rom_tmp, "constant lzss-size");
564 <                        if (s == NULL) {
565 <                                ErrorAlert(GetString(STR_ROM_SIZE_ERR));
566 <                                goto quit;
567 <                        }
568 <                        s -= 7;
569 <                        if (sscanf(s, "%06x", &lzss_size) != 1) {
570 <                                ErrorAlert(GetString(STR_ROM_SIZE_ERR));
571 <                                goto quit;
572 <                        }
573 <                        D(bug("Offset of compressed data: %08x\n", lzss_offset));
574 <                        D(bug("Size of compressed data: %08x\n", lzss_size));
575 <
576 <                        D(bug("Uncompressing ROM...\n"));
577 <                        decode_lzss(rom_tmp + lzss_offset, (uint8 *)ROM_BASE, lzss_size);
578 <                        delete[] rom_tmp;
579 <                } else if (rom_size != 4*1024*1024) {
545 >        
546 >        // Decode Mac ROM
547 >        if (!DecodeROM(rom_tmp, actual)) {
548 >                if (rom_size != 4*1024*1024) {
549                          ErrorAlert(GetString(STR_ROM_SIZE_ERR));
550                          goto quit;
551                  } else {
# Line 584 | Line 553 | int main(int argc, char **argv)
553                          goto quit;
554                  }
555          }
556 +        delete[] rom_tmp;
557  
558          // Load NVRAM
559          XPRAMInit();
560  
561          // Set boot volume
562 <        drive = PrefsFindInt32("bootdrive");
562 >        i16 = PrefsFindInt32("bootdrive");
563          XPRAM[0x1378] = i16 >> 8;
564          XPRAM[0x1379] = i16 & 0xff;
565 <        driver = PrefsFindInt32("bootdriver");
565 >        i16 = PrefsFindInt32("bootdriver");
566          XPRAM[0x137a] = i16 >> 8;
567          XPRAM[0x137b] = i16 & 0xff;
568  
# Line 605 | Line 575 | int main(int argc, char **argv)
575          boot_globs[1] = htonl(RAMSize);
576          boot_globs[2] = htonl((uint32)-1);                      // End of bank table
577  
578 +        // Init thunks
579 +        if (!ThunksInit())
580 +                goto quit;
581 +
582          // Init drivers
583          SonyInit();
584          DiskInit();
# Line 643 | Line 617 | int main(int argc, char **argv)
617   #if !EMULATED_PPC
618          MakeExecutable(0, (void *)ROM_BASE, ROM_AREA_SIZE);
619   #endif
620 <        mprotect((char *)ROM_BASE, ROM_AREA_SIZE, PROT_EXEC | PROT_READ);
620 >        vm_protect((char *)ROM_BASE, ROM_AREA_SIZE, VM_PAGE_READ | VM_PAGE_EXECUTE);
621  
622          // Initialize Kernel Data
623          memset(kernel_data, 0, sizeof(KernelData));
624          if (ROMType == ROMTYPE_NEWWORLD) {
625 <                static uint32 of_dev_tree[4] = {0, 0, 0, 0};
626 <                static uint8 vector_lookup_tbl[128];
627 <                static uint8 vector_mask_tbl[64];
625 >                uintptr of_dev_tree = SheepMem::Reserve(4 * sizeof(uint32));
626 >                memset((void *)of_dev_tree, 0, 4 * sizeof(uint32));
627 >                uintptr vector_lookup_tbl = SheepMem::Reserve(128);
628 >                uintptr vector_mask_tbl = SheepMem::Reserve(64);
629                  memset((uint8 *)kernel_data + 0xb80, 0x3d, 0x80);
630 <                memset(vector_lookup_tbl, 0, 128);
631 <                memset(vector_mask_tbl, 0, 64);
630 >                memset((void *)vector_lookup_tbl, 0, 128);
631 >                memset((void *)vector_mask_tbl, 0, 64);
632                  kernel_data->v[0xb80 >> 2] = htonl(ROM_BASE);
633 <                kernel_data->v[0xb84 >> 2] = htonl((uint32)of_dev_tree);        // OF device tree base
634 <                kernel_data->v[0xb90 >> 2] = htonl((uint32)vector_lookup_tbl);
635 <                kernel_data->v[0xb94 >> 2] = htonl((uint32)vector_mask_tbl);
633 >                kernel_data->v[0xb84 >> 2] = htonl(of_dev_tree);                        // OF device tree base
634 >                kernel_data->v[0xb90 >> 2] = htonl(vector_lookup_tbl);
635 >                kernel_data->v[0xb94 >> 2] = htonl(vector_mask_tbl);
636                  kernel_data->v[0xb98 >> 2] = htonl(ROM_BASE);                           // OpenPIC base
637                  kernel_data->v[0xbb0 >> 2] = htonl(0);                                          // ADB base
638                  kernel_data->v[0xc20 >> 2] = htonl(RAMSize);
# Line 693 | Line 668 | int main(int argc, char **argv)
668          D(bug("Initializing Low Memory...\n"));
669          memset(NULL, 0, 0x3000);
670          WriteMacInt32(XLM_SIGNATURE, FOURCC('B','a','a','h'));                  // Signature to detect SheepShaver
671 <        WriteMacInt32(XLM_KERNEL_DATA, (uint32)kernel_data);                    // For trap replacement routines
671 >        WriteMacInt32(XLM_KERNEL_DATA, KernelDataAddr);                                 // For trap replacement routines
672          WriteMacInt32(XLM_PVR, PVR);                                                                    // Theoretical PVR
673          WriteMacInt32(XLM_BUS_CLOCK, BusClockSpeed);                                    // For DriverServicesLib patch
674          WriteMacInt16(XLM_EXEC_RETURN_OPCODE, M68K_EXEC_RETURN);                // For Execute68k() (RTS from the executed 68k code will jump here and end 68k mode)
675 < #if !EMULATED_PPC
675 > #if EMULATED_PPC
676 >        WriteMacInt32(XLM_ETHER_INIT, NativeFunction(NATIVE_ETHER_INIT));
677 >        WriteMacInt32(XLM_ETHER_TERM, NativeFunction(NATIVE_ETHER_TERM));
678 >        WriteMacInt32(XLM_ETHER_OPEN, NativeFunction(NATIVE_ETHER_OPEN));
679 >        WriteMacInt32(XLM_ETHER_CLOSE, NativeFunction(NATIVE_ETHER_CLOSE));
680 >        WriteMacInt32(XLM_ETHER_WPUT, NativeFunction(NATIVE_ETHER_WPUT));
681 >        WriteMacInt32(XLM_ETHER_RSRV, NativeFunction(NATIVE_ETHER_RSRV));
682 >        WriteMacInt32(XLM_VIDEO_DOIO, NativeFunction(NATIVE_VIDEO_DO_DRIVER_IO));
683 > #else
684          WriteMacInt32(XLM_TOC, (uint32)TOC);                                                    // TOC pointer of emulator
685          WriteMacInt32(XLM_ETHER_INIT, (uint32)InitStreamModule);                // DLPI ethernet driver functions
686          WriteMacInt32(XLM_ETHER_TERM, (uint32)TerminateStreamModule);
# Line 767 | Line 750 | int main(int argc, char **argv)
750                  ErrorAlert(str);
751                  goto quit;
752          }
753 + #endif
754  
755          // Install interrupt signal handler
756          sigemptyset(&sigusr2_action.sa_mask);
757          sigusr2_action.sa_handler = (__sighandler_t)sigusr2_handler;
758 +        sigusr2_action.sa_flags = 0;
759 + #if !EMULATED_PPC
760          sigusr2_action.sa_flags = SA_ONSTACK | SA_RESTART;
761 + #endif
762          sigusr2_action.sa_restorer = NULL;
763          if (sigaction(SIGUSR2, &sigusr2_action, NULL) < 0) {
764                  sprintf(str, GetString(STR_SIGUSR2_INSTALL_ERR), strerror(errno));
765                  ErrorAlert(str);
766                  goto quit;
767          }
781 #endif
768  
769          // Get my thread ID and execute MacOS thread function
770          emul_thread = pthread_self();
# Line 797 | Line 783 | quit:
783  
784   static void Quit(void)
785   {
786 + #if EMULATED_PPC
787 +        // Exit PowerPC emulation
788 +        exit_emul_ppc();
789 + #endif
790 +
791          // Stop 60Hz thread
792          if (tick_thread_active) {
793                  pthread_cancel(tick_thread);
# Line 853 | Line 844 | static void Quit(void)
844          DiskExit();
845          SonyExit();
846  
847 +        // Delete SheepShaver globals
848 +        SheepMem::Exit();
849 +
850          // Delete RAM area
851          if (ram_area_mapped)
852 <                munmap(mmap_RAMBase, RAMSize);
852 >                vm_release((char *)RAM_BASE, RAMSize);
853  
854          // Delete ROM area
855          if (rom_area_mapped)
856 <                munmap((char *)ROM_BASE, ROM_AREA_SIZE);
856 >                vm_release((char *)ROM_BASE, ROM_AREA_SIZE);
857  
858          // Delete Kernel Data area
859          if (kernel_area >= 0) {
# Line 900 | Line 894 | static void Quit(void)
894   */
895  
896   #if EMULATED_PPC
903 extern void emul_ppc(uint32 start);
904 extern void init_emul_ppc(void);
897   void jump_to_rom(uint32 entry)
898   {
899          init_emul_ppc();
# Line 966 | Line 958 | void Execute68kTrap(uint16 trap, M68kReg
958          uint16 proc[2] = {trap, M68K_RTS};
959          Execute68k((uint32)proc, r);
960   }
969 #endif
961  
962  
963   /*
# Line 976 | Line 967 | void Execute68kTrap(uint16 trap, M68kReg
967   void ExecutePPC(void (*func)())
968   {
969          uint32 tvect[2] = {(uint32)func, 0};    // Fake TVECT
970 <        RoutineDescriptor desc = BUILD_PPC_ROUTINE_DESCRIPTOR(0, tvect);
970 >        SheepRoutineDescriptor desc(0, tvect);
971          M68kRegisters r;
972          Execute68k((uint32)&desc, &r);
973   }
974 + #endif
975  
976  
977   /*
# Line 1041 | Line 1033 | void Dump68kRegs(M68kRegisters *r)
1033  
1034   void MakeExecutable(int dummy, void *start, uint32 length)
1035   {
1036 < #if !EMULATED_PPC
1045 <        if (((uint32)start >= ROM_BASE) && ((uint32)start < (ROM_BASE + ROM_SIZE)))
1036 >        if (((uintptr)start >= ROM_BASE) && ((uintptr)start < (ROM_BASE + ROM_SIZE)))
1037                  return;
1038 <        flush_icache_range(start, (void *)((uint32)start + length));
1038 > #if EMULATED_PPC
1039 >        FlushCodeCache((uintptr)start, (uintptr)start + length);
1040 > #else
1041 >        flush_icache_range(start, (void *)((uintptr)start + length));
1042   #endif
1043   }
1044  
# Line 1055 | Line 1049 | void MakeExecutable(int dummy, void *sta
1049  
1050   void PatchAfterStartup(void)
1051   {
1052 + #if EMULATED_PPC
1053 +        ExecuteNative(NATIVE_VIDEO_INSTALL_ACCEL);
1054 + #else
1055          ExecutePPC(VideoInstallAccel);
1056 + #endif
1057          InstallExtFS();
1058   }
1059  
# Line 1158 | Line 1156 | static void *tick_func(void *arg)
1156  
1157   void Set_pthread_attr(pthread_attr_t *attr, int priority)
1158   {
1159 <        // nothing to do
1159 > #ifdef HAVE_PTHREADS
1160 >        pthread_attr_init(attr);
1161 > #if defined(_POSIX_THREAD_PRIORITY_SCHEDULING)
1162 >        // Some of these only work for superuser
1163 >        if (geteuid() == 0) {
1164 >                pthread_attr_setinheritsched(attr, PTHREAD_EXPLICIT_SCHED);
1165 >                pthread_attr_setschedpolicy(attr, SCHED_FIFO);
1166 >                struct sched_param fifo_param;
1167 >                fifo_param.sched_priority = ((sched_get_priority_min(SCHED_FIFO) +
1168 >                                              sched_get_priority_max(SCHED_FIFO)) / 2 +
1169 >                                             priority);
1170 >                pthread_attr_setschedparam(attr, &fifo_param);
1171 >        }
1172 >        if (pthread_attr_setscope(attr, PTHREAD_SCOPE_SYSTEM) != 0) {
1173 > #ifdef PTHREAD_SCOPE_BOUND_NP
1174 >            // If system scope is not available (eg. we're not running
1175 >            // with CAP_SCHED_MGT capability on an SGI box), try bound
1176 >            // scope.  It exposes pthread scheduling to the kernel,
1177 >            // without setting realtime priority.
1178 >            pthread_attr_setscope(attr, PTHREAD_SCOPE_BOUND_NP);
1179 > #endif
1180 >        }
1181 > #endif
1182 > #endif
1183   }
1184  
1185  
# Line 1166 | Line 1187 | void Set_pthread_attr(pthread_attr_t *at
1187   *  Mutexes
1188   */
1189  
1190 + #ifdef HAVE_PTHREADS
1191 +
1192 + struct B2_mutex {
1193 +        B2_mutex() {
1194 +            pthread_mutexattr_t attr;
1195 +            pthread_mutexattr_init(&attr);
1196 +            // Initialize the mutex for priority inheritance --
1197 +            // required for accurate timing.
1198 + #ifdef HAVE_PTHREAD_MUTEXATTR_SETPROTOCOL
1199 +            pthread_mutexattr_setprotocol(&attr, PTHREAD_PRIO_INHERIT);
1200 + #endif
1201 + #if defined(HAVE_PTHREAD_MUTEXATTR_SETTYPE) && defined(PTHREAD_MUTEX_NORMAL)
1202 +            pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_NORMAL);
1203 + #endif
1204 + #ifdef HAVE_PTHREAD_MUTEXATTR_SETPSHARED
1205 +            pthread_mutexattr_setpshared(&attr, PTHREAD_PROCESS_PRIVATE);
1206 + #endif
1207 +            pthread_mutex_init(&m, &attr);
1208 +            pthread_mutexattr_destroy(&attr);
1209 +        }
1210 +        ~B2_mutex() {
1211 +            pthread_mutex_trylock(&m); // Make sure it's locked before
1212 +            pthread_mutex_unlock(&m);  // unlocking it.
1213 +            pthread_mutex_destroy(&m);
1214 +        }
1215 +        pthread_mutex_t m;
1216 + };
1217 +
1218 + B2_mutex *B2_create_mutex(void)
1219 + {
1220 +        return new B2_mutex;
1221 + }
1222 +
1223 + void B2_lock_mutex(B2_mutex *mutex)
1224 + {
1225 +        pthread_mutex_lock(&mutex->m);
1226 + }
1227 +
1228 + void B2_unlock_mutex(B2_mutex *mutex)
1229 + {
1230 +        pthread_mutex_unlock(&mutex->m);
1231 + }
1232 +
1233 + void B2_delete_mutex(B2_mutex *mutex)
1234 + {
1235 +        delete mutex;
1236 + }
1237 +
1238 + #else
1239 +
1240   struct B2_mutex {
1241          int dummy;
1242   };
# Line 1188 | Line 1259 | void B2_delete_mutex(B2_mutex *mutex)
1259          delete mutex;
1260   }
1261  
1262 + #endif
1263 +
1264  
1265   /*
1266   *  Trigger signal USR2 from another thread
1267   */
1268  
1269 + #if !EMULATED_PPC || ASYNC_IRQ
1270   void TriggerInterrupt(void)
1271   {
1198 #if EMULATED_PPC
1199        WriteMacInt32(0x16a, ReadMacInt32(0x16a) + 1);
1200 #else
1201 #if 0
1202        WriteMacInt32(0x16a, ReadMacInt32(0x16a) + 1);
1203 #else
1272          if (ready_for_signals)
1273                  pthread_kill(emul_thread, SIGUSR2);
1206 #endif
1207 #endif
1274   }
1275 + #endif
1276  
1277  
1278   /*
# Line 1245 | Line 1312 | void EnableInterrupt(void)
1312   }
1313  
1314  
1248 #if !EMULATED_PPC
1315   /*
1316   *  USR2 handler
1317   */
1318  
1319 + #if EMULATED_PPC
1320 + static void sigusr2_handler(int sig)
1321 + {
1322 + #if ASYNC_IRQ
1323 +        extern void HandleInterrupt(void);
1324 +        HandleInterrupt();
1325 + #endif
1326 + }
1327 + #else
1328   static void sigusr2_handler(int sig, sigcontext_struct *sc)
1329   {
1330          pt_regs *r = sc->regs;
# Line 1331 | Line 1406 | static void sigusr2_handler(int sig, sig
1406                          }
1407                          break;
1408   #endif
1334
1409          }
1410   }
1411 + #endif
1412  
1413  
1414   /*
1415   *  SIGSEGV handler
1416   */
1417  
1418 + #if !EMULATED_PPC
1419   static void sigsegv_handler(int sig, sigcontext_struct *sc)
1420   {
1421          pt_regs *r = sc->regs;
1422 +
1423 +        // Get effective address
1424 +        uint32 addr = r->dar;
1425 +        
1426 + #if ENABLE_VOSF
1427 +        // Handle screen fault.
1428 +        extern bool Screen_fault_handler(sigsegv_address_t fault_address, sigsegv_address_t fault_instruction);
1429 +        if (Screen_fault_handler((sigsegv_address_t)addr, (sigsegv_address_t)r->nip))
1430 +                return;
1431 + #endif
1432 +
1433          num_segv++;
1434  
1435          // Fault in Mac ROM or RAM?
1436          bool mac_fault = (r->nip >= ROM_BASE) && (r->nip < (ROM_BASE + ROM_AREA_SIZE)) || (r->nip >= RAMBase) && (r->nip < (RAMBase + RAMSize));
1437          if (mac_fault) {
1438  
1352                // Get opcode and divide into fields
1353                uint32 opcode = *((uint32 *)r->nip);
1354                uint32 primop = opcode >> 26;
1355                uint32 exop = (opcode >> 1) & 0x3ff;
1356                uint32 ra = (opcode >> 16) & 0x1f;
1357                uint32 rb = (opcode >> 11) & 0x1f;
1358                uint32 rd = (opcode >> 21) & 0x1f;
1359                int32 imm = (int16)(opcode & 0xffff);
1360
1439                  // "VM settings" during MacOS 8 installation
1440                  if (r->nip == ROM_BASE + 0x488160 && r->gpr[20] == 0xf8000000) {
1441                          r->nip += 4;
# Line 1385 | Line 1463 | static void sigsegv_handler(int sig, sig
1463                          return;
1464                  }
1465  
1466 +                // Get opcode and divide into fields
1467 +                uint32 opcode = *((uint32 *)r->nip);
1468 +                uint32 primop = opcode >> 26;
1469 +                uint32 exop = (opcode >> 1) & 0x3ff;
1470 +                uint32 ra = (opcode >> 16) & 0x1f;
1471 +                uint32 rb = (opcode >> 11) & 0x1f;
1472 +                uint32 rd = (opcode >> 21) & 0x1f;
1473 +                int32 imm = (int16)(opcode & 0xffff);
1474 +
1475                  // Analyze opcode
1476                  enum {
1477                          TYPE_UNKNOWN,
# Line 1468 | Line 1555 | static void sigsegv_handler(int sig, sig
1555                                  transfer_type = TYPE_STORE; transfer_size = SIZE_HALFWORD; addr_mode = MODE_U; break;
1556                  }
1557          
1471                // Calculate effective address
1472                uint32 addr = 0;
1473                switch (addr_mode) {
1474                        case MODE_X:
1475                        case MODE_UX:
1476                                if (ra == 0)
1477                                        addr = r->gpr[rb];
1478                                else
1479                                        addr = r->gpr[ra] + r->gpr[rb];
1480                                break;
1481                        case MODE_NORM:
1482                        case MODE_U:
1483                                if (ra == 0)
1484                                        addr = (int32)(int16)imm;
1485                                else
1486                                        addr = r->gpr[ra] + (int32)(int16)imm;
1487                                break;
1488                        default:
1489                                break;
1490                }
1491
1558                  // Ignore ROM writes
1559                  if (transfer_type == TYPE_STORE && addr >= ROM_BASE && addr < ROM_BASE + ROM_SIZE) {
1560   //                      D(bug("WARNING: %s write access to ROM at %08lx, pc %08lx\n", transfer_size == SIZE_BYTE ? "Byte" : transfer_size == SIZE_HALFWORD ? "Halfword" : "Word", addr, r->nip));
# Line 1725 | Line 1791 | rti:;
1791  
1792  
1793   /*
1794 + *  Helpers to share 32-bit addressable data with MacOS
1795 + */
1796 +
1797 + bool SheepMem::Init(void)
1798 + {
1799 +        if (vm_acquire_fixed((char *)base, size) < 0)
1800 +                return false;
1801 +        top = base + size;
1802 +        return true;
1803 + }
1804 +
1805 + void SheepMem::Exit(void)
1806 + {
1807 +        if (top)
1808 +                vm_release((void *)base, size);
1809 + }
1810 +
1811 +
1812 + /*
1813   *  Display alert
1814   */
1815  

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines