disk.c 2.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129
  1. #include <u.h>
  2. #include <libc.h>
  3. #include <draw.h>
  4. #include <thread.h>
  5. #include <cursor.h>
  6. #include <mouse.h>
  7. #include <keyboard.h>
  8. #include <frame.h>
  9. #include <fcall.h>
  10. #include <plumb.h>
  11. #include "dat.h"
  12. #include "fns.h"
  13. static Block *blist;
  14. int
  15. tempfile(void)
  16. {
  17. char buf[128];
  18. int i, fd;
  19. snprint(buf, sizeof buf, "/tmp/X%d.%.4sacme", getpid(), getuser());
  20. for(i='A'; i<='Z'; i++){
  21. buf[5] = i;
  22. if(access(buf, AEXIST) == 0)
  23. continue;
  24. fd = create(buf, ORDWR|ORCLOSE|OCEXEC, 0600);
  25. if(fd >= 0)
  26. return fd;
  27. }
  28. return -1;
  29. }
  30. Disk*
  31. diskinit()
  32. {
  33. Disk *d;
  34. d = emalloc(sizeof(Disk));
  35. d->fd = tempfile();
  36. if(d->fd < 0){
  37. fprint(2, "acme: can't create temp file: %r\n");
  38. threadexitsall("diskinit");
  39. }
  40. return d;
  41. }
  42. static
  43. uint
  44. ntosize(uint n, uint *ip)
  45. {
  46. uint size;
  47. if(n > Maxblock)
  48. error("internal error: ntosize");
  49. size = n;
  50. if(size & (Blockincr-1))
  51. size += Blockincr - (size & (Blockincr-1));
  52. /* last bucket holds blocks of exactly Maxblock */
  53. if(ip)
  54. *ip = size/Blockincr;
  55. return size * sizeof(Rune);
  56. }
  57. Block*
  58. disknewblock(Disk *d, uint n)
  59. {
  60. uint i, j, size;
  61. Block *b;
  62. size = ntosize(n, &i);
  63. b = d->free[i];
  64. if(b)
  65. d->free[i] = b->next;
  66. else{
  67. /* allocate in chunks to reduce malloc overhead */
  68. if(blist == nil){
  69. blist = emalloc(100*sizeof(Block));
  70. for(j=0; j<100-1; j++)
  71. blist[j].next = &blist[j+1];
  72. }
  73. b = blist;
  74. blist = b->next;
  75. b->addr = d->addr;
  76. d->addr += size;
  77. }
  78. b->n = n;
  79. return b;
  80. }
  81. void
  82. diskrelease(Disk *d, Block *b)
  83. {
  84. uint i;
  85. ntosize(b->n, &i);
  86. b->next = d->free[i];
  87. d->free[i] = b;
  88. }
  89. void
  90. diskwrite(Disk *d, Block **bp, Rune *r, uint n)
  91. {
  92. int size, nsize;
  93. Block *b;
  94. b = *bp;
  95. size = ntosize(b->n, nil);
  96. nsize = ntosize(n, nil);
  97. if(size != nsize){
  98. diskrelease(d, b);
  99. b = disknewblock(d, n);
  100. *bp = b;
  101. }
  102. if(pwrite(d->fd, r, n*sizeof(Rune), b->addr) != n*sizeof(Rune))
  103. error("write error to temp file");
  104. b->n = n;
  105. }
  106. void
  107. diskread(Disk *d, Block *b, Rune *r, uint n)
  108. {
  109. if(n > b->n)
  110. error("internal error: diskread");
  111. ntosize(b->n, nil);
  112. if(pread(d->fd, r, n*sizeof(Rune), b->addr) != n*sizeof(Rune))
  113. error("read error from temp file");
  114. }