diff loader/ldt_keeper.c @ 7386:174e2a58b4cd

avifile sync - 95% cosmetics 5% bug
author arpi
date Fri, 13 Sep 2002 19:43:17 +0000
parents 02576893af2a
children 9d3e1476ecd0
line wrap: on
line diff
--- a/loader/ldt_keeper.c	Fri Sep 13 19:42:33 2002 +0000
+++ b/loader/ldt_keeper.c	Fri Sep 13 19:43:17 2002 +0000
@@ -4,8 +4,13 @@
  * be modified before program creates first thread
  * - avifile includes this file from C++ code
  * and initializes it at the start of player!
+ * it might sound like a hack and it really is - but
+ * as aviplay is deconding video with more than just one
+ * thread currently it's necessary to do it this way
+ * this might change in the future
  */
 
+/* applied some modification to make make our xine friend more happy */
 #include "ldt_keeper.h"
 
 #include <string.h>
@@ -19,6 +24,14 @@
 #ifdef __linux__
 #include <asm/unistd.h>
 #include <asm/ldt.h>
+/* prototype it here, so we won't depend on kernel headers */
+#ifdef  __cplusplus
+extern "C" {
+#endif
+int modify_ldt(int func, void *ptr, unsigned long bytecount);
+#ifdef  __cplusplus
+}
+#endif
 #else
 #if defined(__NetBSD__) || defined(__FreeBSD__) || defined(__OpenBSD__)
 #include <machine/segments.h>
@@ -33,7 +46,7 @@
 #ifdef  __cplusplus
 extern "C" {
 #endif
-extern int sysi86(int, void*);
+int sysi86(int, void*);
 #ifdef  __cplusplus
 }
 #endif
@@ -69,21 +82,14 @@
 /* user level (privilege level: 3) ldt (1<<2) segment selector */
 #define       LDT_SEL(idx) ((idx) << 3 | 1 << 2 | 3)
 
+/* i got this value from wine sources, it's the first free LDT entry */
 #ifndef       TEB_SEL_IDX
-#define       TEB_SEL_IDX     1
+#define       TEB_SEL_IDX     17
 #endif
+
 #define       TEB_SEL LDT_SEL(TEB_SEL_IDX)
 
 /**
- *
- *  This should be performed before we create first thread. See remarks
- *  for write_ldt(), linux/kernel/ldt.c.
- *
- */
-
-void* fs_seg = NULL;
-static char* prev_struct = NULL;
-/**
  * here is a small logical problem with Restore for multithreaded programs -
  * in C++ we use static class for this...
  */
@@ -98,6 +104,8 @@
     );
 }
 
+/* we don't need this - use modify_ldt instead */
+#if 0
 #ifdef __linux__
 /* XXX: why is this routine from libc redefined here? */
 /* NOTE: the redefined version ignores the count param, count is hardcoded as 16 */
@@ -130,6 +138,7 @@
     return -1;
 }
 #endif
+#endif
 
 #if defined(__NetBSD__) || defined(__FreeBSD__) || defined(__OpenBSD__)
 static void LDT_EntryToBytes( unsigned long *buffer, const struct modify_ldt_ldt_s *content )
@@ -147,31 +156,34 @@
 }
 #endif
 
-void Setup_LDT_Keeper(void)
+//void* fs_seg=0;
+
+ldt_fs_t* Setup_LDT_Keeper(void)
 {
     struct modify_ldt_ldt_s array;
-    int fd;
     int ret;
+    ldt_fs_t* ldt_fs = (ldt_fs_t*) malloc(sizeof(ldt_fs_t));
 
-    if (fs_seg)
-        return;
+    if (!ldt_fs)
+	return NULL;
 
-    prev_struct = 0;
-    fd = open("/dev/zero", O_RDWR);
-    if(fd<0){
-        perror( "Cannot open /dev/zero for READ+WRITE. Check permissions! error: " );
-	return;
+    ldt_fs->fd = open("/dev/zero", O_RDWR);
+    if(ldt_fs->fd<0){
+        perror( "Cannot open /dev/zero for READ+WRITE. Check permissions! error: ");
+	return NULL;
     }
-    fs_seg = mmap(NULL, getpagesize(), PROT_READ | PROT_WRITE, MAP_PRIVATE,
-		  fd, 0);
-    if(fs_seg==(void*)-1)
+//    fs_seg=
+    ldt_fs->fs_seg = mmap(NULL, getpagesize(), PROT_READ | PROT_WRITE, MAP_PRIVATE,
+			  ldt_fs->fd, 0);
+    if (ldt_fs->fs_seg == (void*)-1)
     {
 	perror("ERROR: Couldn't allocate memory for fs segment");
-	return;
+        close(ldt_fs->fd);
+        free(ldt_fs);
+	return NULL;
     }
-//    printf("fs seg %p\n", fs_seg);
-    *(void**)((char*)fs_seg+0x18) = fs_seg;
-    array.base_addr=(int)fs_seg;
+    *(void**)((char*)ldt_fs->fs_seg+0x18) = ldt_fs->fs_seg;
+    array.base_addr=(int)ldt_fs->fs_seg;
     array.entry_number=TEB_SEL_IDX;
     array.limit=array.base_addr+getpagesize()-1;
     array.seg_32bit=1;
@@ -180,7 +192,8 @@
     array.contents=MODIFY_LDT_CONTENTS_DATA;
     array.limit_in_pages=0;
 #ifdef __linux__
-    ret=LDT_Modify(0x1, &array, sizeof(struct modify_ldt_ldt_s));
+    //ret=LDT_Modify(0x1, &array, sizeof(struct modify_ldt_ldt_s));
+    ret=modify_ldt(0x1, &array, sizeof(struct modify_ldt_ldt_s));
     if(ret<0)
     {
 	perror("install_fs");
@@ -200,7 +213,6 @@
 	    printf("Couldn't install fs segment, expect segfault\n");
             printf("Did you reconfigure the kernel with \"options USER_LDT\"?\n");
         }
-	printf("Set_LDT\n");
     }
 #endif  /* __NetBSD__ || __FreeBSD__ || __OpenBSD__ */
 
@@ -223,17 +235,20 @@
 
     Setup_FS_Segment();
 
-    prev_struct = (char*)malloc(sizeof(char) * 8);
-    *(void**)array.base_addr = prev_struct;
-    close(fd);
+    ldt_fs->prev_struct = (char*)malloc(sizeof(char) * 8);
+    *(void**)array.base_addr = ldt_fs->prev_struct;
+
+    return ldt_fs;
 }
 
-void Restore_LDT_Keeper(void)
+void Restore_LDT_Keeper(ldt_fs_t* ldt_fs)
 {
-    if (fs_seg == 0)
+    if (ldt_fs == NULL || ldt_fs->fs_seg == 0)
 	return;
-    if (prev_struct)
-	free(prev_struct);
-    munmap((char*)fs_seg, getpagesize());
-    fs_seg = 0;
+    if (ldt_fs->prev_struct)
+	free(ldt_fs->prev_struct);
+    munmap((char*)ldt_fs->fs_seg, getpagesize());
+    ldt_fs->fs_seg = 0;
+    close(ldt_fs->fd);
+    free(ldt_fs);
 }