| 1208 | } |
| 1209 | |
| 1210 | ssize_t MtFrame::write(int fd, const void *buf, size_t nbyte, int timeout) |
| 1211 | { |
| 1212 | MtFrame* mtframe = MtFrame::Instance(); |
| 1213 | utime64_t start = mtframe->GetLastClock(); |
| 1214 | MicroThread* thread = mtframe->GetActiveThread(); |
| 1215 | utime64_t now = 0; |
| 1216 | |
| 1217 | if(fd<0 || !buf || nbyte<1) |
| 1218 | { |
| 1219 | errno = EINVAL; |
| 1220 | MTLOG_ERROR("write failed, errno: %d (%m)", errno); |
| 1221 | return -10; |
| 1222 | } |
| 1223 | |
| 1224 | ssize_t n = 0; |
| 1225 | size_t send_len = 0; |
| 1226 | while (send_len < nbyte) |
| 1227 | { |
| 1228 | now = mtframe->GetLastClock(); |
| 1229 | if ((int)(now - start) > timeout) |
| 1230 | { |
| 1231 | errno = ETIME; |
| 1232 | return -1; |
| 1233 | } |
| 1234 | |
| 1235 | mt_hook_syscall(write); |
| 1236 | n = ff_hook_write(fd, (char*)buf + send_len, nbyte - send_len); |
| 1237 | if (n < 0) |
| 1238 | { |
| 1239 | if (errno == EINTR) { |
| 1240 | continue; |
| 1241 | } |
| 1242 | |
| 1243 | if ((errno != EAGAIN) && (errno != EWOULDBLOCK)) { |
| 1244 | MTLOG_ERROR("write failed, errno: %d", errno); |
| 1245 | return -2; |
| 1246 | } |
| 1247 | } |
| 1248 | else |
| 1249 | { |
| 1250 | send_len += n; |
| 1251 | if (send_len >= nbyte) { |
| 1252 | return nbyte; |
| 1253 | } |
| 1254 | } |
| 1255 | |
| 1256 | KqueuerObj epfd; |
| 1257 | epfd.SetOsfd(fd); |
| 1258 | epfd.EnableOutput(); |
| 1259 | epfd.SetOwnerThread(thread); |
| 1260 | if (!mtframe->KqueueSchedule(NULL, &epfd, timeout)) { |
| 1261 | return -3; |
| 1262 | } |
| 1263 | } |
| 1264 | |
| 1265 | return nbyte; |
| 1266 | } |
| 1267 | |