github.com/keybase/client/go@v0.0.0-20241007131713-f10651d043c8/kbfs/dokan/pointertable.go (about) 1 // Copyright 2016 Keybase Inc. All rights reserved. 2 // Use of this source code is governed by a BSD 3 // license that can be found in the LICENSE file. 4 5 package dokan 6 7 import ( 8 "sync" 9 ) 10 11 /* Keep Go pointers while passing integers to the C heap. 12 * 13 * These tables should only be used through the functions 14 * defined in this file. 15 */ 16 17 var fsTableLock sync.Mutex 18 var fsTable = make([]fsTableEntry, 0, 2) 19 var fiTableLock sync.Mutex // nolint 20 var fiTable = map[uint32]File{} // nolint 21 var fiIdx uint32 // nolint 22 23 type fsTableEntry struct { 24 fs FileSystem 25 errChan chan error 26 fileCount uint32 27 } 28 29 func fsTableStore(fs FileSystem, ec chan error) uint32 { 30 fsTableLock.Lock() 31 defer fsTableLock.Unlock() 32 33 for i, c := range fsTable { 34 if c.fs == nil { 35 fsTable[i] = fsTableEntry{fs: fs, errChan: ec} 36 return uint32(i) 37 } 38 } 39 40 fsTable = append(fsTable, fsTableEntry{fs: fs, errChan: ec}) 41 return uint32(len(fsTable) - 1) 42 } 43 44 func fsTableFree(slot uint32) { // nolint 45 fsTableLock.Lock() 46 defer fsTableLock.Unlock() 47 if int(slot) < len(fsTable) { 48 fsTable[slot] = fsTableEntry{} 49 } 50 } 51 52 func fsTableGet(slot uint32) FileSystem { // nolint 53 fsTableLock.Lock() 54 defer fsTableLock.Unlock() 55 return fsTable[slot].fs 56 } 57 58 func fsTableGetErrChan(slot uint32) chan error { // nolint 59 fsTableLock.Lock() 60 defer fsTableLock.Unlock() 61 return fsTable[slot].errChan 62 } 63 64 func fsTableGetFileCount(slot uint32) uint32 { 65 fsTableLock.Lock() 66 defer fsTableLock.Unlock() 67 return fsTable[slot].fileCount 68 } 69 70 func fiTableStoreFile(global uint32, fi File) uint32 { // nolint 71 fsTableLock.Lock() 72 fsTable[global].fileCount++ 73 fsTableLock.Unlock() 74 fiTableLock.Lock() 75 defer fiTableLock.Unlock() 76 for { 77 // Just use a simple counter (inside the lock) 78 // to look for potential free file handles. 79 // Overflowing the counter is ok, but skip 80 // counter value zero (for better error detection). 81 fiIdx++ 82 if fiIdx == 0 { 83 fiIdx++ 84 } 85 _, exist := fiTable[fiIdx] 86 if !exist { 87 debug("FID alloc", fiIdx, fi) 88 fiTable[fiIdx] = fi 89 return fiIdx 90 } 91 } 92 } 93 94 func fiTableGetFile(file uint32) File { // nolint 95 fiTableLock.Lock() 96 var fi = fiTable[file] 97 fiTableLock.Unlock() 98 debug("FID get", file, fi) 99 return fi 100 } 101 102 func fiTableFreeFile(global uint32, file uint32) { // nolint 103 fsTableLock.Lock() 104 fsTable[global].fileCount-- 105 fsTableLock.Unlock() 106 fiTableLock.Lock() 107 defer fiTableLock.Unlock() 108 debug("FID free", global, file, "=>", fiTable[file], "# of open files:", len(fiTable)-1) 109 delete(fiTable, file) 110 }