disk.c 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148
  1. /*
  2. * This file is part of the UCB release of Plan 9. It is subject to the license
  3. * terms in the LICENSE file found in the top-level directory of this
  4. * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No
  5. * part of the UCB release of Plan 9, including this file, may be copied,
  6. * modified, propagated, or distributed except according to the terms contained
  7. * in the LICENSE file.
  8. */
  9. #include <u.h>
  10. #include <libc.h>
  11. #include <draw.h>
  12. #include <thread.h>
  13. #include <cursor.h>
  14. #include <mouse.h>
  15. #include <keyboard.h>
  16. #include <frame.h>
  17. #include <fcall.h>
  18. #include <plumb.h>
  19. #include "dat.h"
  20. #include "fns.h"
  21. static Block *blist;
  22. int
  23. tempfile(void)
  24. {
  25. char buf[128];
  26. int i, fd;
  27. snprint(buf, sizeof buf, "/tmp/X%d.%.4sacme", getpid(), getuser());
  28. for(i='A'; i<='Z'; i++){
  29. buf[5] = i;
  30. if(access(buf, AEXIST) == 0)
  31. continue;
  32. fd = create(buf, ORDWR|ORCLOSE|OCEXEC, 0600);
  33. if(fd >= 0)
  34. return fd;
  35. }
  36. return -1;
  37. }
  38. Disk*
  39. diskinit()
  40. {
  41. Disk *d;
  42. d = emalloc(sizeof(Disk));
  43. d->fd = tempfile();
  44. if(d->fd < 0){
  45. fprint(2, "acme: can't create temp file: %r\n");
  46. threadexitsall("diskinit");
  47. }
  48. return d;
  49. }
  50. static
  51. u32
  52. ntosize(u32 n, u32 *ip)
  53. {
  54. u32 size;
  55. if(n > Maxblock)
  56. error("internal error: ntosize");
  57. size = n;
  58. if(size & (Blockincr-1))
  59. size += Blockincr - (size & (Blockincr-1));
  60. /* last bucket holds blocks of exactly Maxblock */
  61. if(ip)
  62. *ip = size/Blockincr;
  63. return size * sizeof(Rune);
  64. }
  65. Block*
  66. disknewblock(Disk *d, u32 n)
  67. {
  68. u32 i, j, size;
  69. Block *b;
  70. size = ntosize(n, &i);
  71. b = d->free[i];
  72. if(b)
  73. d->free[i] = b->next;
  74. else{
  75. /* allocate in chunks to reduce malloc overhead */
  76. if(blist == nil){
  77. blist = emalloc(100*sizeof(Block));
  78. for(j=0; j<100-1; j++)
  79. blist[j].next = &blist[j+1];
  80. }
  81. b = blist;
  82. blist = b->next;
  83. b->addr = d->addr;
  84. d->addr += size;
  85. }
  86. b->n = n;
  87. return b;
  88. }
  89. void
  90. diskrelease(Disk *d, Block *b)
  91. {
  92. u32 i;
  93. ntosize(b->n, &i);
  94. b->next = d->free[i];
  95. d->free[i] = b;
  96. }
  97. void
  98. diskwrite(Disk *d, Block **bp, Rune *r, u32 n)
  99. {
  100. int size, nsize;
  101. Block *b;
  102. b = *bp;
  103. size = ntosize(b->n, nil);
  104. nsize = ntosize(n, nil);
  105. if(size != nsize){
  106. diskrelease(d, b);
  107. b = disknewblock(d, n);
  108. *bp = b;
  109. }
  110. if(pwrite(d->fd, r, n*sizeof(Rune), b->addr) != n*sizeof(Rune))
  111. error("write error to temp file");
  112. b->n = n;
  113. }
  114. void
  115. diskread(Disk *d, Block *b, Rune *r, u32 n)
  116. {
  117. int tot, nr;
  118. char *p;
  119. if(n > b->n)
  120. error("internal error: diskread");
  121. ntosize(b->n, nil);
  122. n *= sizeof(Rune);
  123. p = (char*)r;
  124. for(tot = 0; tot < n; tot += nr){
  125. nr = pread(d->fd, p+tot, n-tot, b->addr+tot);
  126. if(nr <= 0)
  127. break; /* tot < n, so error */
  128. }
  129. if(tot != n)
  130. error("read error from temp file");
  131. }