+pthread_mutex_t modify_ldt_lock = PTHREAD_MUTEX_INITIALIZER;
+
+static int
+ldt_index_selector (int index) {
+ return index << 3 | 7;
+}
+
+static int
+find_free_ldt_index () {
+ struct ssd ssd;
+ int usage[65536/sizeof(int)];
+ int i;
+ FILE *fp;
+
+ memset(usage, 0, sizeof(usage));
+
+ fp = fopen("/proc/self/ldt", "r");
+
+ if (fp == NULL) {
+ lose("Couldn't open /proc/self/ldt");
+ }
+
+ while (fread(&ssd, sizeof(ssd), 1, fp) == 1) {
+ int index = ssd.sel >> 3;
+ if (index >= 65536) {
+ lose("segment selector index too large: %d", index);
+ }
+
+ usage[index / sizeof(int)] |= 1 << (index & (sizeof(int)-1));
+ }
+
+ fclose(fp);
+
+ /* Magic number 7 is the first LDT index that Solaris leaves free. */
+ for (i = 7; i < 65536; i++) {
+ if (~usage[i / sizeof(int)] & (1 << (i & (sizeof(int)-1)))) {
+ return i;
+ }
+ }
+
+ lose("Couldn't find a free LDT index");
+}
+
+static int
+install_segment (unsigned long start, unsigned long size) {
+ int selector;
+
+ thread_mutex_lock(&modify_ldt_lock);
+
+ selector = ldt_index_selector(find_free_ldt_index());
+ struct ssd ssd = { selector,
+ start,
+ size,
+ 0xf2,
+ 0x4};
+ if (sysi86(SI86DSCR, &ssd) < 0) {
+ lose("Couldn't install segment for thread-local data");
+ }
+
+ thread_mutex_unlock(&modify_ldt_lock);
+
+ return selector;
+}
+#endif
+