Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add 1 test case for threads #40

Merged
merged 1 commit into from
Jul 7, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions ChangeLog
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
2024-07-07 Konstantin Kushnir <[email protected]>
* Add basic cryptographic functions
* Add 1 test case for threads

2024-06-23 Konstantin Kushnir <[email protected]>
* Bumped version to 1.8.0
Expand Down
2 changes: 2 additions & 0 deletions generic/cookfs.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@
#define __FUNCTION_NAME__ __func__
#endif
#endif
// #define CookfsLog(a) {printf("[%p] ", (void *)Tcl_GetCurrentThread()); a; printf("\n"); fflush(stdout);}
// #define CookfsLog2(a) {printf("[%p] ", (void *)Tcl_GetCurrentThread()); printf("%s: ", __FUNCTION_NAME__); a; printf("\n"); fflush(stdout);}
#define CookfsLog(a) {a; printf("\n"); fflush(stdout);}
#define CookfsLog2(a) {printf("%s: ", __FUNCTION_NAME__); a; printf("\n"); fflush(stdout);}
#else
Expand Down
5 changes: 4 additions & 1 deletion generic/pagesCompr.c
Original file line number Diff line number Diff line change
Expand Up @@ -476,7 +476,7 @@ Cookfs_PageObj Cookfs_ReadPage(Cookfs_Pages *p, int idx, int size, int decompres

p->fileLastOp = COOKFS_LASTOP_READ;

CookfsLog(printf("Cookfs_ReadPage I=%d S=%d C=%d", idx, size, p->fileCompression))
CookfsLog(printf("Cookfs_ReadPage #%d size:%d compression:%d", idx, size, p->fileCompression))
if (size == 0) {
/* if page was empty, no need to read anything */
return Cookfs_PageObjAlloc(0);
Expand Down Expand Up @@ -612,9 +612,12 @@ void Cookfs_SeekToPage(Cookfs_Pages *p, int idx) {
int Cookfs_WritePage(Cookfs_Pages *p, int idx, unsigned char *bytes, int origSize, Tcl_Obj *compressedData) {
Tcl_Size size = -1;

CookfsLog2(printf("page index #%d, original size: %d", idx, origSize));

// Add initial stamp if needed
Cookfs_PageAddStamp(p, 0);

CookfsLog2(printf("fileLastOp: %d", p->fileLastOp));
/* if last operation was not write, we need to seek
* to make sure we're at location where we should be writing */
if ((idx >= 0) && (p->fileLastOp != COOKFS_LASTOP_WRITE)) {
Expand Down
83 changes: 83 additions & 0 deletions tests/vfsThread.test
Original file line number Diff line number Diff line change
Expand Up @@ -1069,3 +1069,86 @@ tcltest::test cookfsVfsThread-8.4 "Accessing a file opened for writing (to small
tcltest::removeFile $file
unset -nocomplain file fsid tid file1 fp result
} -result {1 {} TEST {} {} 1}

tcltest::test cookfsVfsThread-9.1 "Test 2 threads, 1 thread reads, 2 thread writes" -constraints {threaded enabledCVfs} -setup {
set file [tcltest::makeFile {} cookfs.cfs]
set fsid [cookfs::Mount $file $file -compression none -shared -smallfilesize 0 -smallfilebuffer 0 -pagesize 0x100]
for { set i 0 } { $i < 20 } { incr i } {
set fd [open [file join $file "ORIG_$i"] wb]
puts -nonewline $fd $i[string repeat ORIG 0x100]
close $fd
}
set mx [thread::rwmutex create]
set tid1 [thread::create thread::wait]
thread::send $tid1 [list set mx $mx]
thread::send $tid1 [list set file $file]
set tid2 [thread::create thread::wait]
thread::send $tid2 [list set mx $mx]
thread::send $tid2 [list set file $file]
} -body {
# lock mx on write
thread::rwmutex wlock $mx
thread::send -async $tid1 {
thread::rwmutex rlock $mx
set start [clock seconds]
if { [catch {
while { [expr { [clock seconds] - $start }] < 3 } {
# Read all available files and check if they contain the expected data
foreach fn_full [lsort -dictionary [glob -directory $file -type f *]] {
set fn [file tail $fn_full]
set expected [split $fn "_"]
set expected "[lindex $expected 1][string repeat [lindex $expected 0] 0x100]"
set fd [open $fn_full rb]
set data [read $fd]
close $fd
if { $data ne $expected } {
return -code error "file $fn_full contains unexpected data"
}
puts "$fn_full - OK"
# The last file from the 2nd thread is THRD_100. Get out of this
# thread if we found it.
if { $fn eq "THRD_100" } {
return "ok"
}
}
puts "--------NEXT ROUND----------"
}
set ok timeout
} result] && $result ne "ok" } {
set result "ERROR: $result"
}
thread::rwmutex unlock $mx
}
thread::send -async $tid2 {
thread::rwmutex rlock $mx
catch {
for { set i 0 } { $i < 101 } { incr i } {
set fd [open [file join $file "THRD_$i"] wb]
puts -nonewline $fd $i[string repeat THRD 0x100]
close $fd
puts "Created: [file join $file "THRD_$i"]"
}
set ok ok
} result
thread::rwmutex unlock $mx
}
# unlock mx mutex, the threads will start to read/write files
thread::rwmutex unlock $mx
# Give 10ms for thread to lock mx mutex
after 10
# Now try locking the mutex again, since the thread read locked mutex,
# we will wait for the threads to finish the job
thread::rwmutex wlock $mx
# we no longer need the mutex
thread::rwmutex unlock $mx
thread::rwmutex destroy $mx
cookfs::Unmount $file
# let's retrieve the results
list [thread::send $tid1 [list set result]] [thread::send $tid2 [list set result]]
} -cleanup {
catch { thread::release $tid1 }
catch { thread::release $tid2 }
catch { cookfs::Unmount $file }
tcltest::removeFile $file
unset -nocomplain file fsid tid1 tid2 mx i fd
} -result {ok ok}